在此 WebGL 代码中,它的目的是绘制 3 只 3d 猴子和 1 个 3d 地板/平面。
但是每当我为该一层着色器程序创建一个缓冲区时,它就会破坏猴子着色器程序。因此,它不是渲染 3 只猴子,也没有地板,而是不渲染猴子,也没有地板。
我将破坏程序的代码评论为问题代码
这是代码
var RunDemo =函数(vertexShaderText,fragmentShaderText,floorVertexShaderText,floorFragmentShaderText,SusanImage,SusanModel){ console.log('这是工作'); 模型 = SusanModel;
var canvas = document.getElementById('game-surface');
gl = canvas.getContext('webgl');
model = SusanModel;
if (!gl) {
console.log('WebGL not supported, falling back on experimental-webgl');
gl = canvas.getContext('experimental-webgl');
}
if (!gl) {
alert('Your browser does not support WebGL');
}
gl.clearColor(0.75, 0.85, 0.8, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.frontFace(gl.CCW);
gl.cullFace(gl.BACK);
// ------------- Create shaders -------------
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
var floorVertexShader = gl.createShader(gl.VERTEX_SHADER);
var floorFragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertexShader, vertexShaderText);
gl.shaderSource(fragmentShader, fragmentShaderText);
gl.shaderSource(floorVertexShader, floorVertexShaderText);
gl.shaderSource(floorFragmentShader, floorFragmentShaderText);
compileShader('vertex', vertexShader);
compileShader('fragment', fragmentShader);
compileShader('vertex', floorVertexShader);
compileShader('fragment', floorFragmentShader);
var mainShaderProgram = gl.createProgram();
gl.attachShader(mainShaderProgram, vertexShader);
gl.attachShader(mainShaderProgram, fragmentShader);
linkProgram(mainShaderProgram);
var floorShaderProgram = gl.createProgram();
gl.attachShader(floorShaderProgram, floorVertexShader);
gl.attachShader(floorShaderProgram, floorFragmentShader);
linkProgram(floorShaderProgram);
// Create buffer for "susan"
var susanVertices = SusanModel.meshes[0].vertices;
var susanIndices = [].concat.apply([], SusanModel.meshes[0].faces);
var susanTexCoords = SusanModel.meshes[0].texturecoords[0];
var susanNormals = SusanModel.meshes[0].normals;
var susanPosVertexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, susanPosVertexBufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(susanVertices), gl.STATIC_DRAW);
var susanTexCoordVertexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, susanTexCoordVertexBufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(susanTexCoords), gl.STATIC_DRAW);
var susanIndexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, susanIndexBufferObject);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(susanIndices), gl.STATIC_DRAW);
var susanNormalBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, susanNormalBufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(susanNormals), gl.STATIC_DRAW);
// Setup attributes for "susan"
gl.useProgram(mainShaderProgram);
var positionAttribLocationSusan = gl.getAttribLocation(mainShaderProgram, 'vertPosition');
gl.bindBuffer(gl.ARRAY_BUFFER, susanPosVertexBufferObject);
gl.vertexAttribPointer(
positionAttribLocationSusan,
3,
gl.FLOAT,
gl.FALSE,
3 * Float32Array.BYTES_PER_ELEMENT,
0
);
gl.enableVertexAttribArray(positionAttribLocationSusan);
var texCoordAttribLocationSusan = gl.getAttribLocation(mainShaderProgram, 'vertTexCoord');
gl.bindBuffer(gl.ARRAY_BUFFER, susanTexCoordVertexBufferObject);
gl.vertexAttribPointer(
texCoordAttribLocationSusan,
2,
gl.FLOAT,
gl.FALSE,
2 * Float32Array.BYTES_PER_ELEMENT,
0
);
gl.enableVertexAttribArray(texCoordAttribLocationSusan);
var normalAttribLocationSusan = gl.getAttribLocation(mainShaderProgram, 'vertNormal');
gl.bindBuffer(gl.ARRAY_BUFFER, susanNormalBufferObject);
gl.vertexAttribPointer(
normalAttribLocationSusan,
3,
gl.FLOAT,
gl.TRUE,
3 * Float32Array.BYTES_PER_ELEMENT,
0
);
gl.enableVertexAttribArray(normalAttribLocationSusan);
var floorVertices =
[ // X, Y, Z U, V
-1.0, -1.0, -1.0, 1, 1,
-1.0, -1.0, 1.0, 1, 0,
1.0, -1.0, 1.0, 0, 0,
1.0, -1.0, -1.0, 0, 1,
];
var floorIndices =
[
0, 1, 2,
0, 2, 3,
];
// Create buffer for the floor
// PROBLEM CODE (The program renders 3 monkeys without this being here, but with it being here, the program renders nothing)
gl.useProgram(floorShaderProgram);
var floorVertexBufferObject = gl.createBuffer(); // create buffer
gl.bindBuffer(gl.ARRAY_BUFFER, floorVertexBufferObject); // bind buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(floorVertices), gl.STATIC_DRAW); // load data into buffer
var floorIndexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, floorIndexBufferObject);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(floorIndices), gl.STATIC_DRAW);
var positionAttribLocationFloor = gl.getAttribLocation(floorShaderProgram, 'vertPosition'); // get location of attribute in program
var texCoordAttribLocationFloor = gl.getAttribLocation(floorShaderProgram, 'vertTexCoord');
gl.vertexAttribPointer(
positionAttribLocationFloor, // attribute location
3, // number of elements per attribute
gl.FLOAT, // type of elements
gl.FALSE, // normalized
5 * Float32Array.BYTES_PER_ELEMENT, // size of an individual vertex
0 // offset from the beginning of a single vertex to this attribute
);
gl.vertexAttribPointer(
texCoordAttribLocationFloor, // attribute location
2, // number of elements per attribute
gl.FLOAT, // type of elements
gl.FALSE, // normalized
5 * Float32Array.BYTES_PER_ELEMENT, // size of an individual vertex
3 * Float32Array.BYTES_PER_ELEMENT // offset from the beginning of a single vertex to this attribute
);
gl.enableVertexAttribArray(positionAttribLocationFloor);
gl.enableVertexAttribArray(texCoordAttribLocationFloor);
// END OF PROBLEM CODE
// ------------- Create texture -------------
var susanTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, susanTexture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(
gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,
gl.UNSIGNED_BYTE,
SusanImage
);
gl.bindTexture(gl.TEXTURE_2D, null);
var boxTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, boxTexture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(
gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,
gl.UNSIGNED_BYTE,
document.getElementById('crate-image')
);
gl.bindTexture(gl.TEXTURE_2D, null);
// Tell OpenGL state machine which program should be active.
gl.useProgram(floorShaderProgram);
var floorMatWorldUniformLocation = gl.getUniformLocation(floorShaderProgram, 'mWorld');
gl.useProgram(mainShaderProgram);
var matWorldUniformLocation = gl.getUniformLocation(mainShaderProgram, 'mWorld');
var matViewUniformLocation = gl.getUniformLocation(mainShaderProgram, 'mView');
var matProjUniformLocation = gl.getUniformLocation(mainShaderProgram, 'mProj');
var worldMatrix = new Float32Array(16);
var viewMatrix = new Float32Array(16);
var projMatrix = new Float32Array(16);
mat4.identity(worldMatrix);
mat4.lookAt(viewMatrix, [0, 0, -8], [0, 0, 0], [0, 1, 0]);
mat4.perspective(projMatrix, glMatrix.toRadian(45), canvas.width / canvas.height, 0.1, 1000.0);
gl.useProgram(floorShaderProgram);
gl.uniformMatrix4fv(floorMatWorldUniformLocation, gl.FALSE, worldMatrix);
gl.useProgram(mainShaderProgram);
gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, worldMatrix);
gl.uniformMatrix4fv(matViewUniformLocation, gl.FALSE, viewMatrix);
gl.uniformMatrix4fv(matProjUniformLocation, gl.FALSE, projMatrix);
var xRotationMatrix = new Float32Array(16);
var yRotationMatrix = new Float32Array(16);
var objects = [
{ worldMatrix: mat4.create(), coord: [0.0, 0.0, 0.0], type: 'susan' }, // type doesn't do anything yet
{ worldMatrix: mat4.create(), coord: [-3.0, -3.0, 5.0], type: 'susan' },
{ worldMatrix: mat4.create(), coord: [3.0, -3.0, 5.0], type: 'susan' },
{ worldMatrix: mat4.create(), coord: [0.0, -1.0, 0.0], type: 'floor' }
];
// ------------- Lighting information -------------
gl.useProgram(mainShaderProgram);
var ambientUniformLocation = gl.getUniformLocation(mainShaderProgram, 'ambientLightIntensity');
var sunlightDirUniformLocation = gl.getUniformLocation(mainShaderProgram, 'sunlightDirection');
var sunlightIntUniformLocation = gl.getUniformLocation(mainShaderProgram, 'sunlightIntensity');
gl.uniform3f(ambientUniformLocation, 0.2, 0.2, 0.2);
gl.uniform3f(sunlightDirUniformLocation, 3.0, 4.0, -2.0);
gl.uniform3f(sunlightIntUniformLocation, 0.9, 0.9, 0.9);
// ------------- Main loop -------------
var identityMatrix = new Float32Array(16);
mat4.identity(identityMatrix);
var angle = 0;
var loop = function () {
gl.clearColor(0.75, 0.85, 0.8, 1.0);
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
angle = performance.now() / 1000 / 6 * 2 * Math.PI;
index = 0;
// Render objects
for (obj of objects){
index += 1;
if (index == 1){ // susan
mat4.identity(obj.worldMatrix);
mat4.rotate(yRotationMatrix, obj.worldMatrix, angle, [0, 1, 0]);
mat4.rotate(xRotationMatrix, obj.worldMatrix, angle / 4, [1, 0, 0]);
mat4.mul(obj.worldMatrix, yRotationMatrix, xRotationMatrix);
gl.useProgram(mainShaderProgram);
gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, obj.worldMatrix);
gl.bindTexture(gl.TEXTURE_2D, susanTexture);
gl.activeTexture(gl.TEXTURE0);
gl.drawElements(gl.TRIANGLES, susanIndices.length, gl.UNSIGNED_SHORT, 0);
}
else if (index == 2){ // susan
obj.worldMatrix[12] = obj.coord[0]; // x
obj.worldMatrix[13] = obj.coord[1]; // y
obj.worldMatrix[14] = obj.coord[2]; // z
gl.useProgram(mainShaderProgram);
gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, obj.worldMatrix);
gl.bindTexture(gl.TEXTURE_2D, susanTexture);
gl.activeTexture(gl.TEXTURE0);
gl.drawElements(gl.TRIANGLES, susanIndices.length, gl.UNSIGNED_SHORT, 0);
}
else if (index == 3) { // susan
obj.worldMatrix[12] = obj.coord[0]; // x
obj.worldMatrix[13] = obj.coord[1]; // y
obj.worldMatrix[14] = obj.coord[2]; // z
gl.useProgram(mainShaderProgram);
gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, obj.worldMatrix);
gl.bindTexture(gl.TEXTURE_2D, boxTexture);
gl.activeTexture(gl.TEXTURE0);
gl.drawElements(gl.TRIANGLES, susanIndices.length, gl.UNSIGNED_SHORT, 0);
}
else if (index == 4) { // floor
obj.worldMatrix[12] = obj.coord[0]; // x
obj.worldMatrix[13] = obj.coord[1]; // y
obj.worldMatrix[14] = obj.coord[2]; // z
gl.useProgram(floorShaderProgram);
gl.uniformMatrix4fv(floorMatWorldUniformLocation, gl.FALSE, obj.worldMatrix);
gl.bindTexture(gl.TEXTURE_2D, boxTexture);
gl.activeTexture(gl.TEXTURE0);
gl.drawElements(gl.TRIANGLES, floorIndices.length, gl.UNSIGNED_SHORT, 0);
}
}
index = 0;
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
};
顶点属性指针是全局状态,当您定义平面几何缓冲区时,您(部分)覆盖之前为 susan 网格设置的指针。为了进一步澄清这一点,您从着色器查询的属性位置不是唯一的,它们只是顶点属性的索引,因此
positionAttribLocationSusan
很可能与positionAttribLocationFloor
相同,属性位置只是0 到 MAX_VERTEX_ATTRIBS
之间的整数,对 vertexAttribPointer
的调用会将最近绑定的 ARRAY_BUFFER
与全局顶点属性单元 (0-MAX_VERTEX_ATTRIBS
) 相关联,您查询该位置的着色器不会被纳入其中帐户。
这意味着,如果您想从各种缓冲区绘制各种几何图形,则需要绑定缓冲区,设置属性指针并在每次绘制调用之前启用/禁用属性(以防它们发生更改),可以使用以下方法简化此过程 VAO.
因此,对于您的代码来说,这意味着在渲染循环中您想要:
bind susan position buffer
set position attribute pointer
bind susan normal buffer
set normal attribute pointer
[repeat for other susan attributes]
(ensure that bound (and only bound) attributes are enabled)
bind susan shader program
set static uniforms
for each susan object
set object specific uniforms
call draw
bind floor position buffer
set position attribute pointer
[repeat for other floor attributes]
(ensure that bound (and only bound) attributes are enabled)
bind floor shader program
set floor shader uniforms
call draw