提问人:dhhepting 提问时间:11/3/2023 最后编辑:dhhepting 更新时间:11/4/2023 访问量:60
在 2 个不同的 WebGL 应用程序中使用相同的 JS 代码,在 1 个应用程序中工作,但在其他应用程序中失败:vertexAttribute 有问题吗?
same JS code in 2 diiferent WebGL applications, works in 1 but fails in other: problem with vertexAttribute?
问:
我在这里创建了 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);
上面第二个代码段的控制台 .log 语句的输出是 .(注意:代码段控制台包含此输出行,但不显示浏览器(chrome、safari)中出现的错误消息。normalLoc -1
从第一个代码段开始,顶点着色器中 aNormal 的声明:
in vec4 aPosition;
in vec3 aNormal;
out vec4 vColor;
从第二个代码段开始在顶点着色器中声明 aNormal:
in vec4 aPosition;
in vec3 aNormal;
out vec3 N, L, V;
我看过 WEBGL: INVALID_VALUE: vertexAttribPointer: index out of range, INVALID_VALUE: enableVertexAttribArray: index out of range,Webgl 的 getAttribLocation 奇怪地返回 -1。
我看不出我错过了什么。任何帮助都非常感谢!
第 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>
第 2 段(失败)
'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
这些局部变量从不使用,因此从不使用,因此从不使用,并且 GLSL 编译器会优化这些变量,因此在调用 时找不到。NN
aNormal
aNormal
gl.vertexAttribPointer
搜索警告/错误显示大多数问题都来自同一个问题:未使用的属性从 GLSL 中删除。
评论