我在这里创建了 2 个片段,从 https://interactivecomputergraphics.com/8E/Code/06/shadedCube.html 开始。第一个片段按预期工作,但第二个片段却没有。当我在浏览器中运行第二个代码片段时,我在 javascript 控制台上收到以下错误:
WebGL: INVALID_VALUE: vertexAttribPointer: index out of range
WebGL: INVALID_VALUE: enableVertexAttribArray: index out of range
错误对应于 javascript 中的这些语句:
const normalLoc = gl.getAttribLocation(program, 'aNormal');
gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normalLoc);
console.log('normalLoc', normalLoc);
上面第二个片段的 console.log 语句的输出是
normalLoc -1
。 (注意:代码片段控制台包含此行输出,但不显示浏览器(chrome、safari)中出现的错误消息。)
第一个片段中顶点着色器中的法线声明:
in vec4 aPosition;
in vec3 aNormal;
out vec4 vColor;
第二个片段中顶点着色器中的法线声明:
in vec4 aPosition;
in vec3 aNormal;
out vec3 N, L, V;
我查看了WEBGL:INVALID_VALUE:vertexAttribPointer:索引超出范围,INVALID_VALUE:enableVertexAttribArray:索引超出范围和Webgl的getAttribLocation奇怪地返回-1。
我不明白我错过了什么。非常感谢任何帮助!
第一个片段(作品)
'use strict';
function shadedCube() {
let gl;
let program;
const numPositions = 36;
const positionsArray = [];
const normalsArray = [];
const vertices = [
vec4(-0.5, -0.5, 0.5, 1.0),
vec4(-0.5, 0.5, 0.5, 1.0),
vec4(0.5, 0.5, 0.5, 1.0),
vec4(0.5, -0.5, 0.5, 1.0),
vec4(-0.5, -0.5, -0.5, 1.0),
vec4(-0.5, 0.5, -0.5, 1.0),
vec4(0.5, 0.5, -0.5, 1.0),
vec4(0.5, -0.5, -0.5, 1.0)];
const viewerPosition = vec4(0.0, 0.0, 20.0, 0.0);
const lightPosition = vec4(0.0, 2.0, 2.0, 0.0);
const lightAmbient = vec4(0.2, 0.2, 0.2, 1.0);
const lightDiffuse = vec4(1.0, 1.0, 1.0, 1.0);
const lightSpecular = vec4(1.0, 1.0, 1.0, 1.0);
const materialAmbient = vec4(0.0, 0.0, 0.8, 1.0);
const materialDiffuse = vec4(0.8, 0.8, 0.0, 1.0);
const materialSpecular = vec4(0.4, 0.4, 0.4, 1.0);
const materialShininess = 100.0;
const xAxis = 0;
const yAxis = 1;
const zAxis = 2;
const axis = 0;
const theta = vec3(0, 0, 0);
const flag = true;
function quad(a, b, c, d) {
const t1 = subtract(vertices[b], vertices[a]);
const t2 = subtract(vertices[c], vertices[b]);
let normal = cross(t1, t2);
normal = vec3(normal);
console.log('cube face normal', normal[0], normal[1], normal[2]);
positionsArray.push(vertices[a]);
normalsArray.push(normal);
positionsArray.push(vertices[b]);
normalsArray.push(normal);
positionsArray.push(vertices[c]);
normalsArray.push(normal);
positionsArray.push(vertices[a]);
normalsArray.push(normal);
positionsArray.push(vertices[c]);
normalsArray.push(normal);
positionsArray.push(vertices[d]);
normalsArray.push(normal);
}
function colorCube() {
quad(1, 0, 3, 2);
quad(2, 3, 7, 6);
quad(3, 0, 4, 7);
quad(6, 5, 1, 2);
quad(4, 5, 6, 7);
quad(5, 4, 0, 1);
}
window.onload = function init() {
const canvas = document.getElementById('gl-canvas');
gl = canvas.getContext('webgl2');
if (!gl) {
alert( 'WebGL 2.0 is not available');
}
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.8, 0.8, 0.8, 1.0);
gl.enable(gl.DEPTH_TEST);
//
// Load shaders and initialize attribute buffers
//
program = initShaders(gl, 'vertex-shader', 'fragment-shader');
gl.useProgram(program);
// generate the data needed for the cube
colorCube();
console.log('number of normals', normalsArray.length);
const vBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(positionsArray), gl.STATIC_DRAW);
const positionLoc = gl.getAttribLocation(program, 'aPosition');
gl.vertexAttribPointer(positionLoc, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLoc);
console.log('positionLoc', positionLoc);
const nBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, nBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(normalsArray), gl.STATIC_DRAW);
const normalLoc = gl.getAttribLocation(program, 'aNormal');
gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normalLoc);
console.log('normalLoc', normalLoc);
const projectionMatrix = ortho(-1, 1, -1, 1, -100, 100);
const ambientProduct = mult(lightAmbient, materialAmbient);
const diffuseProduct = mult(lightDiffuse, materialDiffuse);
const specularProduct = mult(lightSpecular, materialSpecular);
/*
document.getElementById('ButtonX').onclick = function() {
axis = xAxis;
};
document.getElementById('ButtonY').onclick = function() {
axis = yAxis;
};
document.getElementById('ButtonZ').onclick = function() {
axis = zAxis;
};
document.getElementById('ButtonT').onclick = function() {
flag = !flag;
}; */
gl.uniform4fv(
gl.getUniformLocation(program, 'uAmbientProduct'), ambientProduct);
gl.uniform4fv(
gl.getUniformLocation(program, 'uDiffuseProduct'), diffuseProduct);
gl.uniform4fv(
gl.getUniformLocation(program, 'uSpecularProduct'), specularProduct);
gl.uniform1f(
gl.getUniformLocation(program, 'uShininess'), materialShininess);
gl.uniform4fv(
gl.getUniformLocation(program, 'uLightPosition'), lightPosition);
gl.uniform4fv(
gl.getUniformLocation(program, 'uViewerPosition'), viewerPosition);
gl.uniformMatrix4fv(
gl.getUniformLocation(program, 'uProjectionMatrix'),
false, flatten(projectionMatrix));
render();
};
function render() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if (flag) {
theta[axis] += 2.0;
}
let modelViewMatrix = mat4();
modelViewMatrix = mult(modelViewMatrix,
rotate(theta[xAxis], vec3(1, 0, 0)));
modelViewMatrix = mult(modelViewMatrix,
rotate(theta[yAxis], vec3(0, 1, 0)));
modelViewMatrix = mult(modelViewMatrix,
rotate(theta[zAxis], vec3(0, 0, 1)));
gl.uniformMatrix4fv(
gl.getUniformLocation(program, 'uModelViewMatrix'),
false, flatten(modelViewMatrix));
gl.drawArrays(gl.TRIANGLES, 0, numPositions);
requestAnimationFrame(render);
};
};
shadedCube();
<!DOCTYPE html>
<html>
<head>
<script id="vertex-shader" type="x-shader/x-vertex">
#version 300 es
in vec4 aPosition;
in vec3 aNormal;
out vec4 vColor;
uniform vec4 uAmbientProduct, uDiffuseProduct, uSpecularProduct;
uniform float uShininess;
uniform mat4 uModelViewMatrix, uProjectionMatrix;
uniform vec4 uLightPosition, uViewerPosition;
void main()
{
vec4 NN = vec4(aNormal, 0);
vec3 N = normalize((uModelViewMatrix * NN).xyz);
vec3 pos = (uModelViewMatrix * aPosition).xyz;
vec3 light = uLightPosition.xyz;
vec3 L = normalize(light - pos);
vec3 V = normalize(uViewerPosition).xyz;
vec3 H = normalize(L + V);
// Compute terms in the illumination equation
// ambient
vec4 ambient = uAmbientProduct;
// diffuse
float Kd = max(dot(L, N), 0.0);
vec4 diffuse = Kd * uDiffuseProduct;
// specular
float Ks = pow(max(dot(N, H), 0.0), uShininess);
vec4 specular = Ks * uSpecularProduct;
vColor = ambient + diffuse + specular;
vColor.a = 1.0;
gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
#version 300 es
precision mediump float;
in vec4 vColor;
out vec4 fColor;
void
main()
{
fColor = vColor;
}
</script>
<script text/javascript" src="https://interactivecomputergraphics.com/8E/Code/Common/initShaders.js"></script>
<script type="text/javascript" src="https://interactivecomputergraphics.com/8E/Code/Common/MVnew.js"></script>
<script type="text/javascript" src="shaded-cube.js"></script>
</head>
<body>
<canvas id="gl-canvas" width="512" height="512">
Your browser does not support the HTML5 canvas element
</canvas>
</body>
</html>
第二个片段(失败)
'use strict';
function shadedCube() {
let gl;
let program;
const numPositions = 36;
const positionsArray = [];
const normalsArray = [];
const vertices = [
vec4(-0.5, -0.5, 0.5, 1.0),
vec4(-0.5, 0.5, 0.5, 1.0),
vec4(0.5, 0.5, 0.5, 1.0),
vec4(0.5, -0.5, 0.5, 1.0),
vec4(-0.5, -0.5, -0.5, 1.0),
vec4(-0.5, 0.5, -0.5, 1.0),
vec4(0.5, 0.5, -0.5, 1.0),
vec4(0.5, -0.5, -0.5, 1.0)];
const viewerPosition = vec4(0.0, 0.0, 20.0, 0.0);
const lightPosition = vec4(0.0, 2.0, 2.0, 0.0);
const lightAmbient = vec4(0.2, 0.2, 0.2, 1.0);
const lightDiffuse = vec4(1.0, 1.0, 1.0, 1.0);
const lightSpecular = vec4(1.0, 1.0, 1.0, 1.0);
const materialAmbient = vec4(0.0, 0.0, 0.8, 1.0);
const materialDiffuse = vec4(0.8, 0.8, 0.0, 1.0);
const materialSpecular = vec4(0.4, 0.4, 0.4, 1.0);
const materialShininess = 100.0;
const xAxis = 0;
const yAxis = 1;
const zAxis = 2;
const axis = 0;
const theta = vec3(0, 0, 0);
const flag = true;
function quad(a, b, c, d) {
const t1 = subtract(vertices[b], vertices[a]);
const t2 = subtract(vertices[c], vertices[b]);
let normal = cross(t1, t2);
normal = vec3(normal);
console.log('cube face normal', normal[0], normal[1], normal[2]);
positionsArray.push(vertices[a]);
normalsArray.push(normal);
positionsArray.push(vertices[b]);
normalsArray.push(normal);
positionsArray.push(vertices[c]);
normalsArray.push(normal);
positionsArray.push(vertices[a]);
normalsArray.push(normal);
positionsArray.push(vertices[c]);
normalsArray.push(normal);
positionsArray.push(vertices[d]);
normalsArray.push(normal);
}
function colorCube() {
quad(1, 0, 3, 2);
quad(2, 3, 7, 6);
quad(3, 0, 4, 7);
quad(6, 5, 1, 2);
quad(4, 5, 6, 7);
quad(5, 4, 0, 1);
}
window.onload = function init() {
const canvas = document.getElementById('gl-canvas');
gl = canvas.getContext('webgl2');
if (!gl) {
alert( 'WebGL 2.0 is not available');
}
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.8, 0.8, 0.8, 1.0);
gl.enable(gl.DEPTH_TEST);
//
// Load shaders and initialize attribute buffers
//
program = initShaders(gl, 'vertex-shader', 'fragment-shader');
gl.useProgram(program);
// generate the data needed for the cube
colorCube();
console.log('number of normals', normalsArray.length);
const vBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(positionsArray), gl.STATIC_DRAW);
const positionLoc = gl.getAttribLocation(program, 'aPosition');
gl.vertexAttribPointer(positionLoc, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLoc);
console.log('positionLoc', positionLoc);
const nBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, nBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(normalsArray), gl.STATIC_DRAW);
const normalLoc = gl.getAttribLocation(program, 'aNormal');
gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normalLoc);
console.log('normalLoc', normalLoc);
const projectionMatrix = ortho(-1, 1, -1, 1, -100, 100);
const ambientProduct = mult(lightAmbient, materialAmbient);
const diffuseProduct = mult(lightDiffuse, materialDiffuse);
const specularProduct = mult(lightSpecular, materialSpecular);
gl.uniform4fv(
gl.getUniformLocation(program, 'uAmbientProduct'), ambientProduct);
gl.uniform4fv(
gl.getUniformLocation(program, 'uDiffuseProduct'), diffuseProduct);
gl.uniform4fv(
gl.getUniformLocation(program, 'uSpecularProduct'), specularProduct);
gl.uniform1f(
gl.getUniformLocation(program, 'uShininess'), materialShininess);
gl.uniform4fv(
gl.getUniformLocation(program, 'uLightPosition'), lightPosition);
gl.uniform4fv(
gl.getUniformLocation(program, 'uViewerPosition'), viewerPosition);
gl.uniformMatrix4fv(
gl.getUniformLocation(program, 'uProjectionMatrix'),
false, flatten(projectionMatrix));
render();
};
function render() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if (flag) {
theta[axis] += 2.0;
}
let modelViewMatrix = mat4();
modelViewMatrix = mult(modelViewMatrix,
rotate(theta[xAxis], vec3(1, 0, 0)));
modelViewMatrix = mult(modelViewMatrix,
rotate(theta[yAxis], vec3(0, 1, 0)));
modelViewMatrix = mult(modelViewMatrix,
rotate(theta[zAxis], vec3(0, 0, 1)));
gl.uniformMatrix4fv(
gl.getUniformLocation(program, 'uModelViewMatrix'),
false, flatten(modelViewMatrix));
gl.drawArrays(gl.TRIANGLES, 0, numPositions);
requestAnimationFrame(render);
};
};
shadedCube();
<!DOCTYPE html>
<html>
<head>
<script id="vertex-shader" type="x-shader/x-vertex">
#version 300 es
in vec4 aPosition;
in vec3 aNormal;
out vec3 N, L, V;
uniform mat4 uModelViewMatrix, uProjectionMatrix;
uniform vec4 uLightPosition, uViewerPosition;
void main()
{
vec3 pos = (uModelViewMatrix * aPosition).xyz;
vec3 light = uLightPosition.xyz;
vec4 NN = vec4(aNormal,0.0);
vec3 N = normalize((uModelViewMatrix * NN).xyz);
vec3 L = normalize(light - pos);
vec3 V = normalize(uViewerPosition).xyz;
gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
#version 300 es
precision mediump float;
in vec3 N, L, V;
out vec4 fColor;
uniform vec4 uAmbientProduct, uDiffuseProduct, uSpecularProduct;
uniform float uShininess;
void main()
{
vec3 H = normalize(L + V);
vec4 ambient = uAmbientProduct;
float Kd = max( dot(L, N), 0.0 );
vec4 diffuse = Kd * uDiffuseProduct;
float Ks = pow(max(dot(N, H), 0.0), uShininess);
vec4 specular = Ks * uSpecularProduct;
fColor = ambient + diffuse + specular;
fColor.a = 1.0;
}
</script>
<script type="text/javascript" src="https://interactivecomputergraphics.com/8E/Code/Common/initShaders.js"></script>
<script type="text/javascript" src="https://interactivecomputergraphics.com/8E/Code/Common/MVnew.js"></script>
<script type="text/javascript" src="shaded-cube.js"></script>
</head>
<body>
<canvas id="gl-canvas" width="512" height="512">
Your browser does not support the HTML5 canvas element
</canvas>
</body>
</html>
发生这种情况是因为您在这些行上有错字:
vec3 N = normalize((uModelViewMatrix * NN).xyz);
vec3 L = normalize(light - pos);
vec3 V = normalize(uViewerPosition).xyz;
您不是设置为
out
变量,而是创建新的局部变量。您需要从所有这些行的开头删除 vec3
。
这些局部变量永远不会被使用,所以
NN
永远不会被使用,所以 aNormal
也永远不会被使用,并且 GLSL 编译器优化掉这些变量,所以当你调用 aNormal
时找不到 gl.vertexAttribPointer
。
搜索警告/错误显示大多数问题都来自同一个问题:未使用的属性从 GLSL 中删除。