目标:当您通过相应的滑块更改zNear、zFar、radius、theta、phi、fov和aspect的值时,我正试图显示具有不同
透视图的三角金字塔。按钮旋转x,y,z是在不同的轴上旋转金字塔。
问题:到目前为止,我想出了下面的代码,一切看起来都很好,但我没有看到金字塔,当我试图显示HTML文件时,它出错了。
var canvas;
var gl;
var NumVertices = 12;
var pointsArray = [];
var colorsArray = [];
var xAxis = 0;
var yAxis = 1;
var zAxis = 2;
var axis = 0;
var theta = [ 0, 0, 0 ];
var near = 0.3;
var far = 3.0;
var radius = 4.0;
var theta = 0.0;
var phi = 0.0;
var dr = 5.0 * Math.PI/180.0;
//var thetaLoc;
var fovy = 45.0; // Field-of-view in Y direction angle (in degrees)
var aspect = 1.0; // Viewport aspect ratio
var modelViewMatrix, projectionMatrix;
var modelViewMatrixLoc, projectionMatrixLoc;
var eye;
const at = vec3(0.0, 0.0, 0.0);
const up = vec3(0.0, 1.0, 0.0);
var vertices = [
vec3(0.5, -0.2722, 0.2886),
vec3(0.0, -0.2722, -0.5773),
vec3(-0.5, -0.2722, 0.2886),
vec3(0.5, -0.5443, 0.0)
]
var vertexColors = [
[ 0.0, 0.0, 0.0, 1.0 ], // black
[ 1.0, 0.0, 0.0, 1.0 ], // red
[ 1.0, 1.0, 0.0, 1.0 ], // yellow
[ 0.0, 1.0, 0.0, 1.0 ] // green
];
window.onload = function init()
{
canvas = document.getElementById( "gl-canvas" );
gl = WebGLUtils.setupWebGL( canvas );
if ( !gl ) { alert( "WebGL isn't available" ); }
gl.viewport( 0, 0, canvas.width, canvas.height );
aspect = canvas.width/canvas.height;
gl.clearColor( 1.0, 1.0, 1.0, 1.0 );
gl.enable(gl.DEPTH_TEST);
//
// Load shaders and initialize attribute buffers
//
var program = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( program );
colorPyramid();
var cBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer);
gl.bufferData( gl.ARRAY_BUFFER, flatten(colorsArray), gl.STATIC_DRAW );
var vColor = gl.getAttribLocation( program, "vColor" );
gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vColor);
var vBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer);
gl.bufferData( gl.ARRAY_BUFFER, flatten(pointsArray), gl.STATIC_DRAW );
var vPosition = gl.getAttribLocation( program, "vPosition" );
gl.vertexAttribPointer( vPosition, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );
modelViewMatrixLoc = gl.getUniformLocation( program, "modelViewMatrix" );
projectionMatrixLoc = gl.getUniformLocation( program, "projectionMatrix" );
// sliders for viewing parameters
document.getElementById("zFarSlider").onchange = function() {
far = event.srcElement.value;
};
document.getElementById("zNearSlider").onchange = function() {
near = event.srcElement.value;
};
document.getElementById("radiusSlider").onchange = function() {
radius = event.srcElement.value;
};
document.getElementById("thetaSlider").onchange = function() {
theta = event.srcElement.value* Math.PI/180.0;
};
document.getElementById("phiSlider").onchange = function() {
phi = event.srcElement.value* Math.PI/180.0;
};
document.getElementById("aspectSlider").onchange = function() {
aspect = event.srcElement.value;
};
document.getElementById("fovSlider").onchange = function() {
fovy = event.srcElement.value;
};
render();
}
function colorPyramid()
{
quad( 0, 1, 2 ); // bottom
quad( 1, 0, 3 ); // side0
quad( 1, 2, 3 ); // side1
quad( 2, 0, 3 ); // side3
}
function quad(a, b, c)
{
var indices = [ a, b, c];
var ndx = pointsArray.length % vertexColors.length;
for ( var i = 0; i < indices.length; ++i ) {
pointsArray.push( vertices[indices[i]] );
colorsArray.push(vertexColors[ndx]);
}
}
function render()
{
// gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
theta[axis] += 2.0;
// gl.uniform3fv(thetaLoc, theta);
// gl.drawArrays( gl.TRIANGLES, 0, NumVertices );
// requestAnimFrame( render );
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
eye = vec3(radius*Math.sin(theta)*Math.cos(phi),
radius*Math.sin(theta)*Math.sin(phi), radius*Math.cos(theta));
modelViewMatrix = lookAt(eye, at , up);
projectionMatrix = perspective(fovy, aspect, near, far);
gl.uniformMatrix4fv( modelViewMatrixLoc, false, flatten(modelViewMatrix) );
gl.uniformMatrix4fv( projectionMatrixLoc, false, flatten(projectionMatrix) );
gl.drawArrays( gl.TRIANGLES, 0, NumVertices );
requestAnimFrame(render);
}
<div>
zNear .01<input id="zNearSlider" type="range"
min=".01" max="3" step="0.1" value="0.3" />
3
</div>
<div>
zFar 3<input id="zFarSlider" type="range"
min="3" max="10" step="3.0" value="3" />
10
</div>
<div>
radius 0.05<input id="radiusSlider" type="range"
min="0.05" max="10" step="0.1" value="4" />
10
</div>
<div>
theta -90<input id="thetaSlider" type="range"
min="-90" max="90" step="5" value="0" />
90
</div>
<div>
phi -90<input id="phiSlider" type="range"
min="-90" max="90" step="5" value="0" />
90
</div>
<div>
fov 10<input id="fovSlider" type="range"
min="10" max="120" step="5" value="45" />
120
</div>
<div>
aspect 0.5<input id="aspectSlider" type="range"
min="0.5" max="2" step="0.1" value="1" />
2
</div>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec4 vColor;
varying vec4 fColor;
uniform vec3 theta;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main()
{
// Compute the sines and cosines of theta for each of
// the three axes in one computation.
<!-- vec3 angles = radians( theta ); -->
<!-- vec3 c = cos( angles ); -->
<!-- vec3 s = sin( angles ); -->
<!-- // Remeber: thse matrices are column-major -->
<!-- mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0, -->
<!-- 0.0, c.x, s.x, 0.0, -->
<!-- 0.0, -s.x, c.x, 0.0, -->
<!-- 0.0, 0.0, 0.0, 1.0 ); -->
<!-- mat4 ry = mat4( c.y, 0.0, -s.y, 0.0, -->
<!-- 0.0, 1.0, 0.0, 0.0, -->
<!-- s.y, 0.0, c.y, 0.0, -->
<!-- 0.0, 0.0, 0.0, 1.0 ); -->
<!-- mat4 rz = mat4( c.z, -s.z, 0.0, 0.0, -->
<!-- s.z, c.z, 0.0, 0.0, -->
<!-- 0.0, 0.0, 1.0, 0.0, -->
<!-- 0.0, 0.0, 0.0, 1.0 ); -->
<!-- fColor = vColor; -->
<!-- gl_Position = rz * ry * rx * vPosition; -->
gl_Position = projectionMatrix*modelViewMatrix*vPosition;
fColor = vColor;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 fColor;
void
main()
{
gl_FragColor = fColor;
}
</script>
<script src="https://esangel.github.io/WebGL/Common/webgl-utils.js"></script>
<script src="https://esangel.github.io/WebGL/Common/initShaders.js"></script>
<script src="https://esangel.github.io/WebGL/Common/MV.js"></script>
<script type="text/javascript" src="Pyramid.js"></script>
<body>
<canvas id="gl-canvas" width="512"" height="512">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
<br/>
<button id= "xButton">Rotate X</button>
<button id= "yButton">Rotate Y</button>
<button id= "zButton">Rotate Z</button>
有几个问题
-
<!-- ... -->
不是GLSL着色器内的有效注释。使用/* ... */
或`// -
调用
gl.vertexAttribPointer
时,位置的代码大小为4。它需要是3。 -
该代码有两个名为
theta
的变量。一个是数字,另一个是数组,代码试图同时使用它们。避免此问题的一种方法是使用let
而不是var
。var
在这一点上基本上是不赞成的。如果使用let
,则会出现错误。还要将"use strict";
放在JavaScript的顶部。这将有助于查找更多错误。我把其中一个改名为a2 -
从视图看,棱锥体是4个单位,但截头体的远平面设置为3,因此棱锥体在截头体之外
-
视图的旋转每帧旋转+2,但旋转是以弧度为单位的,因此+2大约是周围的1/3,因此旋转速度太快。
'use strict';
let canvas;
let gl;
let NumVertices = 12;
let pointsArray = [];
let colorsArray = [];
let xAxis = 0;
let yAxis = 1;
let zAxis = 2;
let axis = 0;
let theta = [ 0, 0, 0 ];
let near = 0.3;
let far = 10.0;
let radius = 4.0;
let theta2 = 0.0;
let phi = 0.0;
let dr = 5.0 * Math.PI/180.0;
//var thetaLoc;
let fovy = 45.0; // Field-of-view in Y direction angle (in degrees)
let aspect = 1.0; // Viewport aspect ratio
let modelViewMatrix, projectionMatrix;
let modelViewMatrixLoc, projectionMatrixLoc;
let eye;
const at = vec3(0.0, 0.0, 0.0);
const up = vec3(0.0, 1.0, 0.0);
var vertices = [
vec3(0.5, -0.2722, 0.2886),
vec3(0.0, -0.2722, -0.5773),
vec3(-0.5, -0.2722, 0.2886),
vec3(0.5, -0.5443, 0.0)
]
var vertexColors = [
[ 0.0, 0.0, 0.0, 1.0 ], // black
[ 1.0, 0.0, 0.0, 1.0 ], // red
[ 1.0, 1.0, 0.0, 1.0 ], // yellow
[ 0.0, 1.0, 0.0, 1.0 ] // green
];
window.onload = function init()
{
canvas = document.getElementById( "gl-canvas" );
gl = WebGLUtils.setupWebGL( canvas );
if ( !gl ) { alert( "WebGL isn't available" ); }
gl.viewport( 0, 0, canvas.width, canvas.height );
aspect = canvas.width/canvas.height;
gl.clearColor( 1.0, 1.0, 1.0, 1.0 );
gl.enable(gl.DEPTH_TEST);
//
// Load shaders and initialize attribute buffers
//
let program = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( program );
colorPyramid();
let cBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer);
gl.bufferData( gl.ARRAY_BUFFER, flatten(colorsArray), gl.STATIC_DRAW );
let vColor = gl.getAttribLocation( program, "vColor" );
gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vColor);
let vBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer);
gl.bufferData( gl.ARRAY_BUFFER, flatten(pointsArray), gl.STATIC_DRAW );
let vPosition = gl.getAttribLocation( program, "vPosition" );
gl.vertexAttribPointer( vPosition, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );
modelViewMatrixLoc = gl.getUniformLocation( program, "modelViewMatrix" );
projectionMatrixLoc = gl.getUniformLocation( program, "projectionMatrix" );
// sliders for viewing parameters
document.getElementById("zFarSlider").onchange = function() {
far = event.srcElement.value;
};
document.getElementById("zNearSlider").onchange = function() {
near = event.srcElement.value;
};
document.getElementById("radiusSlider").onchange = function() {
radius = event.srcElement.value;
};
document.getElementById("thetaSlider").onchange = function() {
theta2 = event.srcElement.value* Math.PI/180.0;
};
document.getElementById("phiSlider").onchange = function() {
phi = event.srcElement.value* Math.PI/180.0;
};
document.getElementById("aspectSlider").onchange = function() {
aspect = event.srcElement.value;
};
document.getElementById("fovSlider").onchange = function() {
fovy = event.srcElement.value;
};
render();
}
function colorPyramid()
{
quad( 0, 1, 2 ); // bottom
quad( 1, 0, 3 ); // side0
quad( 1, 2, 3 ); // side1
quad( 2, 0, 3 ); // side3
}
function quad(a, b, c)
{
let indices = [ a, b, c];
let ndx = pointsArray.length % vertexColors.length;
for ( let i = 0; i < indices.length; ++i ) {
pointsArray.push( vertices[indices[i]] );
colorsArray.push(vertexColors[ndx]);
}
}
function render()
{
// gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
theta[axis] += 2.0;
theta2 += .02;
// gl.uniform3fv(thetaLoc, theta);
// gl.drawArrays( gl.TRIANGLES, 0, NumVertices );
// requestAnimFrame( render );
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
eye = vec3(radius*Math.sin(theta2)*Math.cos(phi),
radius*Math.sin(theta2)*Math.sin(phi), radius*Math.cos(theta2));
modelViewMatrix = lookAt(eye, at , up);
projectionMatrix = perspective(fovy, aspect, near, far);
gl.uniformMatrix4fv( modelViewMatrixLoc, false, flatten(modelViewMatrix) );
gl.uniformMatrix4fv( projectionMatrixLoc, false, flatten(projectionMatrix) );
gl.drawArrays( gl.TRIANGLES, 0, NumVertices );
requestAnimFrame(render);
}
<div>
zNear .01<input id="zNearSlider" type="range"
min=".01" max="3" step="0.1" value="0.3" />
3
</div>
<div>
zFar 3<input id="zFarSlider" type="range"
min="3" max="10" step="3.0" value="3" />
10
</div>
<div>
radius 0.05<input id="radiusSlider" type="range"
min="0.05" max="10" step="0.1" value="4" />
10
</div>
<div>
theta -90<input id="thetaSlider" type="range"
min="-90" max="90" step="5" value="0" />
90
</div>
<div>
phi -90<input id="phiSlider" type="range"
min="-90" max="90" step="5" value="0" />
90
</div>
<div>
fov 10<input id="fovSlider" type="range"
min="10" max="120" step="5" value="45" />
120
</div>
<div>
aspect 0.5<input id="aspectSlider" type="range"
min="0.5" max="2" step="0.1" value="1" />
2
</div>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec4 vColor;
varying vec4 fColor;
uniform vec3 theta;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main()
{
// Compute the sines and cosines of theta for each of
// the three axes in one computation.
//<!-- vec3 angles = radians( theta ); -->
//<!-- vec3 c = cos( angles ); -->
//<!-- vec3 s = sin( angles ); -->
//<!-- // Remeber: thse matrices are column-major -->
//<!-- mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0, -->
// <!-- 0.0, c.x, s.x, 0.0, -->
// <!-- 0.0, -s.x, c.x, 0.0, -->
// <!-- 0.0, 0.0, 0.0, 1.0 ); -->
//<!-- mat4 ry = mat4( c.y, 0.0, -s.y, 0.0, -->
// <!-- 0.0, 1.0, 0.0, 0.0, -->
// <!-- s.y, 0.0, c.y, 0.0, -->
// <!-- 0.0, 0.0, 0.0, 1.0 ); -->
//<!-- mat4 rz = mat4( c.z, -s.z, 0.0, 0.0, -->
// <!-- s.z, c.z, 0.0, 0.0, -->
// <!-- 0.0, 0.0, 1.0, 0.0, -->
// <!-- 0.0, 0.0, 0.0, 1.0 ); -->
//<!-- fColor = vColor; -->
//<!-- gl_Position = rz * ry * rx * vPosition; -->
gl_Position = projectionMatrix*modelViewMatrix*vPosition;
fColor = vColor;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 fColor;
void
main()
{
gl_FragColor = fColor;
}
</script>
<script src="https://esangel.github.io/WebGL/Common/webgl-utils.js"></script>
<script src="https://esangel.github.io/WebGL/Common/initShaders.js"></script>
<script src="https://esangel.github.io/WebGL/Common/MV.js"></script>
<canvas id="gl-canvas" width="512"" height="512">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
<br/>
<button id= "xButton">Rotate X</button>
<button id= "yButton">Rotate Y</button>
<button id= "zButton">Rotate Z</button>
其他提示
-
了解如何使用片段
-
通过链接到您使用的库,使您的代码可以运行
<script src="https://esangel.github.io/WebGL/Common/webgl-utils.js"></script>
<script src="https://esangel.github.io/WebGL/Common/initShaders.js"></script>
<script src="https://esangel.github.io/WebGL/Common/MV.js"></script>
考虑添加webgl lint以帮助查找错误。
从一些不同的教训中学习。