WebGL 使用 gl.drawElements() 只渲染顶点,不渲染三角形
WebGL render only vertices, but not triangles using gl.drawElements()
我正在尝试渲染一个索引立方体(使用重复顶点来实现平面着色)。我设置了一个位置缓冲区,一个索引缓冲区,设置着色器输入并使用 gl.drawElements(gl.TRIANGLES, ...)
:
绘制它
但是,在屏幕上,我只看到顶点,但没有渲染三角形。
我在每次 gl 调用后都打印了 gl.getError()
,但所有 return 0(没有错误)。这是现场演示(可以通过单击并拖动 canvas 来旋转立方体):
function printError(gl, msg)
{
console.log(msg + " " + gl.getError());
}
let clicking = false;
let lastXPos = -1;
let lastYPos = -1;
let rotationSpeed = 0.5 // (deg/pixel) 0.1 degree rotation on a given axis per pixel
let pitch = 0.0
let maxPitch = 90.0
let yaw = 0.0
let projMatrix = Object();
let modelViewMatrix = Object();
let buffers = Object();
let programInfo = Object();
function deg2Rad(degrees)
{
return degrees * (Math.PI / 180.0);
}
function main_gl()
{
const canvas = document.querySelector('#glcanvas');
const gl = canvas.getContext('webgl2');
// If we don't have a GL context, give up now
if (!gl)
{
alert('Unable to initialize WebGL. Your browser or machine may not support it.');
return;
}
// Vertex shader program
const vsSource = `
attribute vec4 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
}
`;
// Fragment shader program
const fsSource = `
void main(void) {
gl_FragColor = vec4(1, 1, 1, 1);
}
`;
// Initialize a shader program; this is where all the lighting
// for the vertices and so forth is established.
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
// Collect all the info needed to use the shader program.
// Look up which attributes our shader program is using
// for aVertexPosition, aVevrtexColor and also
// look up uniform locations.
programInfo =
{
program: shaderProgram,
attribLocations:
{
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
vertexColor: gl.getAttribLocation(shaderProgram, 'aVertexColor'),
},
uniformLocations:
{
projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
},
};
printError(gl, "Attributes and uniform gathered");
setUpInputCallbacks(canvas, gl);
// Here's where we call the routine that builds all the
// objects we'll be drawing.
buffers = initBuffers(gl);
setUpScene(gl);
// Draw the scene
drawScene(gl);
}
// ================================================================================================
function initBuffers(gl)
{
const positions = [
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
];
const positionBuffer = gl.createBuffer();
printError(gl, "Position buffer created");
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
printError(gl, "Position bufffer binded");
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
printError(gl, "Position buffer filled");
const indices = [
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
15, 16, 17,
18, 19, 20,
21, 22, 23,
24, 25, 26,
27, 28, 29,
30, 31, 32,
33, 34, 35,
];
var indexBuffer = gl.createBuffer ();
printError(gl, "Index buffer created");
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
printError(gl, "Index buffer binded");
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
printError(gl, "Index buffer filled");
return {
indices: indexBuffer,
position: positionBuffer,
};
}
// ================================================================================================
function setUpScene(gl)
{
const fieldOfView = 45 * Math.PI / 180; // in radians
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const zNear = 0.1;
const zFar = 100.0;
projMatrix = mat4.create();
// note: glmatrix.js always has the first argument
// as the destination to receive the result.
mat4.perspective(projMatrix,
fieldOfView,
aspect,
zNear,
zFar);
modelViewMatrix = mat4.create();
const vNumComponents = 3;
const vType = gl.FLOAT;
const vNormalize = false;
const vStride = 0;
const vOffset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
printError(gl, "Bind position buffer");
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
vNumComponents,
vType,
vNormalize,
vStride,
vOffset);
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
printError(gl, "Setted shader position input");
}
function drawScene(gl)
{
printError(gl, "Draw scene begin");
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0); // Clear everything
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
printError(gl, "OpenGL configured");
mat4.identity(modelViewMatrix);
mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]);
mat4.rotateX(modelViewMatrix, modelViewMatrix, deg2Rad(pitch));
mat4.rotateY(modelViewMatrix, modelViewMatrix, deg2Rad(yaw));
// Tell WebGL to use our program when drawing
gl.useProgram(programInfo.program);
printError(gl, "Bind program");
// Set the shader uniforms
gl.uniformMatrix4fv(
programInfo.uniformLocations.projectionMatrix,
false,
projMatrix);
gl.uniformMatrix4fv(
programInfo.uniformLocations.modelViewMatrix,
false,
modelViewMatrix);
printError(gl, "Setted uniforms");
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.indices);
printError(gl, "Bind index buffer");
gl.drawElements(gl.GL_LINES, 36, gl.UNSIGNED_SHORT, 0);
printError(gl, "Drawing");
}
// ================================================================================================
function initShaderProgram(gl, vsSource, fsSource)
{
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
const shaderProgram = gl.createProgram();
printError(gl, "Program created");
gl.attachShader(shaderProgram, vertexShader);
printError(gl, "Vertex shader attached");
gl.attachShader(shaderProgram, fragmentShader);
printError(gl, "Fragment shader attached");
gl.linkProgram(shaderProgram);
printError(gl, "Program linked");
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
{
alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
return null;
}
return shaderProgram;
}
// ================================================================================================
function loadShader(gl, type, source)
{
const shader = gl.createShader(type);
printError(gl, "Shader created");
gl.shaderSource(shader, source);
printError(gl, "Shader source setted");
gl.compileShader(shader);
printError(gl, "Shader compiled");
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
{
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function setUpInputCallbacks(canvas, gl)
{
canvas.onmousedown = function(event)
{
clicking = event.button === 0;
}
canvas.onmouseup = function(event)
{
clicking = !event.button === 0;
lastXPos = -1;
lastYPos = -1;
}
canvas.onmousemove = function(event)
{
if(clicking)
{
if(lastXPos === -1 || lastYPos === -1)
{
lastXPos = event.clientX;
lastYPos = event.clientY;
}
else
{
xDiff = lastXPos - event.clientX;
yDiff = lastYPos - event.clientY;
lastXPos = event.clientX;
lastYPos = event.clientY;
rotatePitch = yDiff * rotationSpeed;
rotateYaw = xDiff * rotationSpeed;
pitch += rotatePitch;
pitchSign = pitch / Math.abs(pitch);
if(isNaN(pitchSign))
pitchSign = 1.0;
pitch = Math.min(Math.abs(pitch), maxPitch);
pitch *= pitchSign;
yaw += rotateYaw;
drawScene(gl);
}
}
}
canvas.onmouseout = function(event)
{
lastXPos = -1;
lastYPos = -1;
}
}
canvas {
border: 2px solid black;
background-color: black;
}
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"
integrity="sha512-zhHQR0/H5SEBL3Wn6yYSaTTZej12z0hVZKOv3TwCUXT1z5qeqGcXJLLrbERYRScEDDpYIJhPC1fk31gqR783iQ=="
crossorigin="anonymous" defer>
</script>
</head>
<body onload="main_gl()">
<canvas id="glcanvas" width="640" height="480"></canvas>
</body>
知道哪里出了问题吗?
GL_LINES
和 GL_TRIANGLES
不是有效的 WebGL 枚举器常量。但是,LINES
和 TRIANGLES
有效:
gl.drawElements(gl.GL_LINES, 36, gl.UNSIGNED_SHORT, 0);
gl.drawElements(gl.LINES, 36, gl.UNSIGNED_SHORT, 0);
gl.drawElements(gl.GL_TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
function printError(gl, msg)
{
console.log(msg + " " + gl.getError());
}
let clicking = false;
let lastXPos = -1;
let lastYPos = -1;
let rotationSpeed = 0.5 // (deg/pixel) 0.1 degree rotation on a given axis per pixel
let pitch = 0.0
let maxPitch = 90.0
let yaw = 0.0
let projMatrix = Object();
let modelViewMatrix = Object();
let buffers = Object();
let programInfo = Object();
function deg2Rad(degrees)
{
return degrees * (Math.PI / 180.0);
}
function main_gl()
{
const canvas = document.querySelector('#glcanvas');
const gl = canvas.getContext('webgl2');
// If we don't have a GL context, give up now
if (!gl)
{
alert('Unable to initialize WebGL. Your browser or machine may not support it.');
return;
}
// Vertex shader program
const vsSource = `
attribute vec4 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
}
`;
// Fragment shader program
const fsSource = `
void main(void) {
gl_FragColor = vec4(1, 1, 1, 1);
}
`;
// Initialize a shader program; this is where all the lighting
// for the vertices and so forth is established.
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
// Collect all the info needed to use the shader program.
// Look up which attributes our shader program is using
// for aVertexPosition, aVevrtexColor and also
// look up uniform locations.
programInfo =
{
program: shaderProgram,
attribLocations:
{
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
vertexColor: gl.getAttribLocation(shaderProgram, 'aVertexColor'),
},
uniformLocations:
{
projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
},
};
printError(gl, "Attributes and uniform gathered");
setUpInputCallbacks(canvas, gl);
// Here's where we call the routine that builds all the
// objects we'll be drawing.
buffers = initBuffers(gl);
setUpScene(gl);
// Draw the scene
drawScene(gl);
}
// ================================================================================================
function initBuffers(gl)
{
const positions = [
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
];
const positionBuffer = gl.createBuffer();
printError(gl, "Position buffer created");
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
printError(gl, "Position bufffer binded");
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
printError(gl, "Position buffer filled");
const indices = [
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
15, 16, 17,
18, 19, 20,
21, 22, 23,
24, 25, 26,
27, 28, 29,
30, 31, 32,
33, 34, 35,
];
var indexBuffer = gl.createBuffer ();
printError(gl, "Index buffer created");
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
printError(gl, "Index buffer binded");
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
printError(gl, "Index buffer filled");
return {
indices: indexBuffer,
position: positionBuffer,
};
}
// ================================================================================================
function setUpScene(gl)
{
const fieldOfView = 45 * Math.PI / 180; // in radians
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const zNear = 0.1;
const zFar = 100.0;
projMatrix = mat4.create();
// note: glmatrix.js always has the first argument
// as the destination to receive the result.
mat4.perspective(projMatrix,
fieldOfView,
aspect,
zNear,
zFar);
modelViewMatrix = mat4.create();
const vNumComponents = 3;
const vType = gl.FLOAT;
const vNormalize = false;
const vStride = 0;
const vOffset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
printError(gl, "Bind position buffer");
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
vNumComponents,
vType,
vNormalize,
vStride,
vOffset);
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
printError(gl, "Setted shader position input");
}
function drawScene(gl)
{
printError(gl, "Draw scene begin");
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0); // Clear everything
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
printError(gl, "OpenGL configured");
mat4.identity(modelViewMatrix);
mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]);
mat4.rotateX(modelViewMatrix, modelViewMatrix, deg2Rad(pitch));
mat4.rotateY(modelViewMatrix, modelViewMatrix, deg2Rad(yaw));
// Tell WebGL to use our program when drawing
gl.useProgram(programInfo.program);
printError(gl, "Bind program");
// Set the shader uniforms
gl.uniformMatrix4fv(
programInfo.uniformLocations.projectionMatrix,
false,
projMatrix);
gl.uniformMatrix4fv(
programInfo.uniformLocations.modelViewMatrix,
false,
modelViewMatrix);
printError(gl, "Setted uniforms");
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.indices);
printError(gl, "Bind index buffer");
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
printError(gl, "Drawing");
}
// ================================================================================================
function initShaderProgram(gl, vsSource, fsSource)
{
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
const shaderProgram = gl.createProgram();
printError(gl, "Program created");
gl.attachShader(shaderProgram, vertexShader);
printError(gl, "Vertex shader attached");
gl.attachShader(shaderProgram, fragmentShader);
printError(gl, "Fragment shader attached");
gl.linkProgram(shaderProgram);
printError(gl, "Program linked");
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
{
alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
return null;
}
return shaderProgram;
}
// ================================================================================================
function loadShader(gl, type, source)
{
const shader = gl.createShader(type);
printError(gl, "Shader created");
gl.shaderSource(shader, source);
printError(gl, "Shader source setted");
gl.compileShader(shader);
printError(gl, "Shader compiled");
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
{
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function setUpInputCallbacks(canvas, gl)
{
canvas.onmousedown = function(event)
{
clicking = event.button === 0;
}
canvas.onmouseup = function(event)
{
clicking = !event.button === 0;
lastXPos = -1;
lastYPos = -1;
}
canvas.onmousemove = function(event)
{
if(clicking)
{
if(lastXPos === -1 || lastYPos === -1)
{
lastXPos = event.clientX;
lastYPos = event.clientY;
}
else
{
xDiff = lastXPos - event.clientX;
yDiff = lastYPos - event.clientY;
lastXPos = event.clientX;
lastYPos = event.clientY;
rotatePitch = yDiff * rotationSpeed;
rotateYaw = xDiff * rotationSpeed;
pitch += rotatePitch;
pitchSign = pitch / Math.abs(pitch);
if(isNaN(pitchSign))
pitchSign = 1.0;
pitch = Math.min(Math.abs(pitch), maxPitch);
pitch *= pitchSign;
yaw += rotateYaw;
drawScene(gl);
}
}
}
canvas.onmouseout = function(event)
{
lastXPos = -1;
lastYPos = -1;
}
}
canvas {
border: 2px solid black;
background-color: black;
}
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"
integrity="sha512-zhHQR0/H5SEBL3Wn6yYSaTTZej12z0hVZKOv3TwCUXT1z5qeqGcXJLLrbERYRScEDDpYIJhPC1fk31gqR783iQ=="
crossorigin="anonymous" defer>
</script>
</head>
<body onload="main_gl()">
<canvas id="glcanvas" width="640" height="480"></canvas>
</body>
我正在尝试渲染一个索引立方体(使用重复顶点来实现平面着色)。我设置了一个位置缓冲区,一个索引缓冲区,设置着色器输入并使用 gl.drawElements(gl.TRIANGLES, ...)
:
但是,在屏幕上,我只看到顶点,但没有渲染三角形。
我在每次 gl 调用后都打印了 gl.getError()
,但所有 return 0(没有错误)。这是现场演示(可以通过单击并拖动 canvas 来旋转立方体):
function printError(gl, msg)
{
console.log(msg + " " + gl.getError());
}
let clicking = false;
let lastXPos = -1;
let lastYPos = -1;
let rotationSpeed = 0.5 // (deg/pixel) 0.1 degree rotation on a given axis per pixel
let pitch = 0.0
let maxPitch = 90.0
let yaw = 0.0
let projMatrix = Object();
let modelViewMatrix = Object();
let buffers = Object();
let programInfo = Object();
function deg2Rad(degrees)
{
return degrees * (Math.PI / 180.0);
}
function main_gl()
{
const canvas = document.querySelector('#glcanvas');
const gl = canvas.getContext('webgl2');
// If we don't have a GL context, give up now
if (!gl)
{
alert('Unable to initialize WebGL. Your browser or machine may not support it.');
return;
}
// Vertex shader program
const vsSource = `
attribute vec4 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
}
`;
// Fragment shader program
const fsSource = `
void main(void) {
gl_FragColor = vec4(1, 1, 1, 1);
}
`;
// Initialize a shader program; this is where all the lighting
// for the vertices and so forth is established.
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
// Collect all the info needed to use the shader program.
// Look up which attributes our shader program is using
// for aVertexPosition, aVevrtexColor and also
// look up uniform locations.
programInfo =
{
program: shaderProgram,
attribLocations:
{
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
vertexColor: gl.getAttribLocation(shaderProgram, 'aVertexColor'),
},
uniformLocations:
{
projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
},
};
printError(gl, "Attributes and uniform gathered");
setUpInputCallbacks(canvas, gl);
// Here's where we call the routine that builds all the
// objects we'll be drawing.
buffers = initBuffers(gl);
setUpScene(gl);
// Draw the scene
drawScene(gl);
}
// ================================================================================================
function initBuffers(gl)
{
const positions = [
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
];
const positionBuffer = gl.createBuffer();
printError(gl, "Position buffer created");
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
printError(gl, "Position bufffer binded");
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
printError(gl, "Position buffer filled");
const indices = [
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
15, 16, 17,
18, 19, 20,
21, 22, 23,
24, 25, 26,
27, 28, 29,
30, 31, 32,
33, 34, 35,
];
var indexBuffer = gl.createBuffer ();
printError(gl, "Index buffer created");
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
printError(gl, "Index buffer binded");
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
printError(gl, "Index buffer filled");
return {
indices: indexBuffer,
position: positionBuffer,
};
}
// ================================================================================================
function setUpScene(gl)
{
const fieldOfView = 45 * Math.PI / 180; // in radians
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const zNear = 0.1;
const zFar = 100.0;
projMatrix = mat4.create();
// note: glmatrix.js always has the first argument
// as the destination to receive the result.
mat4.perspective(projMatrix,
fieldOfView,
aspect,
zNear,
zFar);
modelViewMatrix = mat4.create();
const vNumComponents = 3;
const vType = gl.FLOAT;
const vNormalize = false;
const vStride = 0;
const vOffset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
printError(gl, "Bind position buffer");
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
vNumComponents,
vType,
vNormalize,
vStride,
vOffset);
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
printError(gl, "Setted shader position input");
}
function drawScene(gl)
{
printError(gl, "Draw scene begin");
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0); // Clear everything
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
printError(gl, "OpenGL configured");
mat4.identity(modelViewMatrix);
mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]);
mat4.rotateX(modelViewMatrix, modelViewMatrix, deg2Rad(pitch));
mat4.rotateY(modelViewMatrix, modelViewMatrix, deg2Rad(yaw));
// Tell WebGL to use our program when drawing
gl.useProgram(programInfo.program);
printError(gl, "Bind program");
// Set the shader uniforms
gl.uniformMatrix4fv(
programInfo.uniformLocations.projectionMatrix,
false,
projMatrix);
gl.uniformMatrix4fv(
programInfo.uniformLocations.modelViewMatrix,
false,
modelViewMatrix);
printError(gl, "Setted uniforms");
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.indices);
printError(gl, "Bind index buffer");
gl.drawElements(gl.GL_LINES, 36, gl.UNSIGNED_SHORT, 0);
printError(gl, "Drawing");
}
// ================================================================================================
function initShaderProgram(gl, vsSource, fsSource)
{
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
const shaderProgram = gl.createProgram();
printError(gl, "Program created");
gl.attachShader(shaderProgram, vertexShader);
printError(gl, "Vertex shader attached");
gl.attachShader(shaderProgram, fragmentShader);
printError(gl, "Fragment shader attached");
gl.linkProgram(shaderProgram);
printError(gl, "Program linked");
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
{
alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
return null;
}
return shaderProgram;
}
// ================================================================================================
function loadShader(gl, type, source)
{
const shader = gl.createShader(type);
printError(gl, "Shader created");
gl.shaderSource(shader, source);
printError(gl, "Shader source setted");
gl.compileShader(shader);
printError(gl, "Shader compiled");
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
{
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function setUpInputCallbacks(canvas, gl)
{
canvas.onmousedown = function(event)
{
clicking = event.button === 0;
}
canvas.onmouseup = function(event)
{
clicking = !event.button === 0;
lastXPos = -1;
lastYPos = -1;
}
canvas.onmousemove = function(event)
{
if(clicking)
{
if(lastXPos === -1 || lastYPos === -1)
{
lastXPos = event.clientX;
lastYPos = event.clientY;
}
else
{
xDiff = lastXPos - event.clientX;
yDiff = lastYPos - event.clientY;
lastXPos = event.clientX;
lastYPos = event.clientY;
rotatePitch = yDiff * rotationSpeed;
rotateYaw = xDiff * rotationSpeed;
pitch += rotatePitch;
pitchSign = pitch / Math.abs(pitch);
if(isNaN(pitchSign))
pitchSign = 1.0;
pitch = Math.min(Math.abs(pitch), maxPitch);
pitch *= pitchSign;
yaw += rotateYaw;
drawScene(gl);
}
}
}
canvas.onmouseout = function(event)
{
lastXPos = -1;
lastYPos = -1;
}
}
canvas {
border: 2px solid black;
background-color: black;
}
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"
integrity="sha512-zhHQR0/H5SEBL3Wn6yYSaTTZej12z0hVZKOv3TwCUXT1z5qeqGcXJLLrbERYRScEDDpYIJhPC1fk31gqR783iQ=="
crossorigin="anonymous" defer>
</script>
</head>
<body onload="main_gl()">
<canvas id="glcanvas" width="640" height="480"></canvas>
</body>
知道哪里出了问题吗?
GL_LINES
和 GL_TRIANGLES
不是有效的 WebGL 枚举器常量。但是,LINES
和 TRIANGLES
有效:
gl.drawElements(gl.GL_LINES, 36, gl.UNSIGNED_SHORT, 0);
gl.drawElements(gl.LINES, 36, gl.UNSIGNED_SHORT, 0);
gl.drawElements(gl.GL_TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
function printError(gl, msg)
{
console.log(msg + " " + gl.getError());
}
let clicking = false;
let lastXPos = -1;
let lastYPos = -1;
let rotationSpeed = 0.5 // (deg/pixel) 0.1 degree rotation on a given axis per pixel
let pitch = 0.0
let maxPitch = 90.0
let yaw = 0.0
let projMatrix = Object();
let modelViewMatrix = Object();
let buffers = Object();
let programInfo = Object();
function deg2Rad(degrees)
{
return degrees * (Math.PI / 180.0);
}
function main_gl()
{
const canvas = document.querySelector('#glcanvas');
const gl = canvas.getContext('webgl2');
// If we don't have a GL context, give up now
if (!gl)
{
alert('Unable to initialize WebGL. Your browser or machine may not support it.');
return;
}
// Vertex shader program
const vsSource = `
attribute vec4 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
}
`;
// Fragment shader program
const fsSource = `
void main(void) {
gl_FragColor = vec4(1, 1, 1, 1);
}
`;
// Initialize a shader program; this is where all the lighting
// for the vertices and so forth is established.
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
// Collect all the info needed to use the shader program.
// Look up which attributes our shader program is using
// for aVertexPosition, aVevrtexColor and also
// look up uniform locations.
programInfo =
{
program: shaderProgram,
attribLocations:
{
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
vertexColor: gl.getAttribLocation(shaderProgram, 'aVertexColor'),
},
uniformLocations:
{
projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
},
};
printError(gl, "Attributes and uniform gathered");
setUpInputCallbacks(canvas, gl);
// Here's where we call the routine that builds all the
// objects we'll be drawing.
buffers = initBuffers(gl);
setUpScene(gl);
// Draw the scene
drawScene(gl);
}
// ================================================================================================
function initBuffers(gl)
{
const positions = [
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
];
const positionBuffer = gl.createBuffer();
printError(gl, "Position buffer created");
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
printError(gl, "Position bufffer binded");
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
printError(gl, "Position buffer filled");
const indices = [
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
15, 16, 17,
18, 19, 20,
21, 22, 23,
24, 25, 26,
27, 28, 29,
30, 31, 32,
33, 34, 35,
];
var indexBuffer = gl.createBuffer ();
printError(gl, "Index buffer created");
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
printError(gl, "Index buffer binded");
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
printError(gl, "Index buffer filled");
return {
indices: indexBuffer,
position: positionBuffer,
};
}
// ================================================================================================
function setUpScene(gl)
{
const fieldOfView = 45 * Math.PI / 180; // in radians
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const zNear = 0.1;
const zFar = 100.0;
projMatrix = mat4.create();
// note: glmatrix.js always has the first argument
// as the destination to receive the result.
mat4.perspective(projMatrix,
fieldOfView,
aspect,
zNear,
zFar);
modelViewMatrix = mat4.create();
const vNumComponents = 3;
const vType = gl.FLOAT;
const vNormalize = false;
const vStride = 0;
const vOffset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
printError(gl, "Bind position buffer");
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
vNumComponents,
vType,
vNormalize,
vStride,
vOffset);
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
printError(gl, "Setted shader position input");
}
function drawScene(gl)
{
printError(gl, "Draw scene begin");
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0); // Clear everything
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
printError(gl, "OpenGL configured");
mat4.identity(modelViewMatrix);
mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]);
mat4.rotateX(modelViewMatrix, modelViewMatrix, deg2Rad(pitch));
mat4.rotateY(modelViewMatrix, modelViewMatrix, deg2Rad(yaw));
// Tell WebGL to use our program when drawing
gl.useProgram(programInfo.program);
printError(gl, "Bind program");
// Set the shader uniforms
gl.uniformMatrix4fv(
programInfo.uniformLocations.projectionMatrix,
false,
projMatrix);
gl.uniformMatrix4fv(
programInfo.uniformLocations.modelViewMatrix,
false,
modelViewMatrix);
printError(gl, "Setted uniforms");
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.indices);
printError(gl, "Bind index buffer");
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
printError(gl, "Drawing");
}
// ================================================================================================
function initShaderProgram(gl, vsSource, fsSource)
{
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
const shaderProgram = gl.createProgram();
printError(gl, "Program created");
gl.attachShader(shaderProgram, vertexShader);
printError(gl, "Vertex shader attached");
gl.attachShader(shaderProgram, fragmentShader);
printError(gl, "Fragment shader attached");
gl.linkProgram(shaderProgram);
printError(gl, "Program linked");
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
{
alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
return null;
}
return shaderProgram;
}
// ================================================================================================
function loadShader(gl, type, source)
{
const shader = gl.createShader(type);
printError(gl, "Shader created");
gl.shaderSource(shader, source);
printError(gl, "Shader source setted");
gl.compileShader(shader);
printError(gl, "Shader compiled");
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
{
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function setUpInputCallbacks(canvas, gl)
{
canvas.onmousedown = function(event)
{
clicking = event.button === 0;
}
canvas.onmouseup = function(event)
{
clicking = !event.button === 0;
lastXPos = -1;
lastYPos = -1;
}
canvas.onmousemove = function(event)
{
if(clicking)
{
if(lastXPos === -1 || lastYPos === -1)
{
lastXPos = event.clientX;
lastYPos = event.clientY;
}
else
{
xDiff = lastXPos - event.clientX;
yDiff = lastYPos - event.clientY;
lastXPos = event.clientX;
lastYPos = event.clientY;
rotatePitch = yDiff * rotationSpeed;
rotateYaw = xDiff * rotationSpeed;
pitch += rotatePitch;
pitchSign = pitch / Math.abs(pitch);
if(isNaN(pitchSign))
pitchSign = 1.0;
pitch = Math.min(Math.abs(pitch), maxPitch);
pitch *= pitchSign;
yaw += rotateYaw;
drawScene(gl);
}
}
}
canvas.onmouseout = function(event)
{
lastXPos = -1;
lastYPos = -1;
}
}
canvas {
border: 2px solid black;
background-color: black;
}
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"
integrity="sha512-zhHQR0/H5SEBL3Wn6yYSaTTZej12z0hVZKOv3TwCUXT1z5qeqGcXJLLrbERYRScEDDpYIJhPC1fk31gqR783iQ=="
crossorigin="anonymous" defer>
</script>
</head>
<body onload="main_gl()">
<canvas id="glcanvas" width="640" height="480"></canvas>
</body>