I am modifying sample code at https://interactivecomputergraphics.com/8E/Code/06/shadedCube.html. Pared-down versions of this code are found in vertex.html (see below, which does more work in its vertex shader) and fragment.html (see below, which does more work in its fragment shader). The fragment.html file is based on vertex.html and shadedSphere2.html / shadedSphere4.html files from the same directory as shadedCube.html on the https://interactivecomputergraphics.com/ website. Both HTML files use the same JS file, shaded-cube.js (see below).
I can load and run vertex.html (using shaded-cube.js) but I get errors when I try to load and run fragment.html (which also uses shaded-cube.js):
WebGL: INVALID_VALUE: vertexAttribPointer: index out of range
WebGL: INVALID_VALUE: enableVertexAttribArray: index out of range
The errors correspond to these statements in shaded-cube.js:
const normalLoc = gl.getAttribLocation(program, 'aNormal');
gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normalLoc);
console.log('normalLoc', normalLoc);
And the output of the console.log statement above for fragment.html is normalLoc -1.
I don’t understand the source of the error – I realize that I may be missing something obvious. Why does shaded-cube.js work for vertex.html and not for fragment.html?
I have looked at WEBGL: INVALID_VALUE: vertexAttribPointer: index out of range, INVALID_VALUE: enableVertexAttribArray: index out of range and tried to apply it to my situation.
Any help is greatly appreciated.
vertex.html
<!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 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>
fragment.html
<!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>
shaded-cube.js
'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();

