我是 Webgl 的新手,一直在遵循许多指南来创建一个具有插值颜色的 3d 立方体,颜色被插值并且动画正在运行。但是,我需要的形状是一个 3D 立方体,而不是一个 3D 金字塔,我终究无法弄清楚为什么。
这是我的代码
//Defing Vector shader
var VSHADER_SOURCE =
'precision mediump float;\n '+
'attribute vec3 vertPosition;\n '+
'attribute vec3 vertColor;\n '+
'uniform mat4 mWorld;\n '+
'uniform mat4 mView;\n '+
'uniform mat4 mProj;\n '+
'varying vec3 vColor;\n '+
'void main()\n '+
'{\n '+
' vColor = vertColor;\n '+
' gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);\n '+
'}'
//Defining Fragment Shader
var FSHADER_SOURCE =
'precision mediump float;\n '+
'varying vec3 vColor;\n '+
'void main()\n '+
'{\n '+
' gl_FragColor = vec4(vColor, 1.0);\n '+
'}';
//Defining vertices for rectangular cube
var boxVertices =
[ // X, Y, Z
// Front face
-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0,
// Back face
-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0,
// Top face
-1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
// Bottom face
-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
// Right face
1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0,
// Left face
-1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0,
];
//Defining indices for rectangular cube
var boxIndices =
[
0,
1,
2,
0,
2,
3, // front
4,
5,
6,
4,
6,
7, // back
8,
9,
10,
8,
10,
11, // top
12,
13,
14,
12,
14,
15, // bottom
16,
17,
18,
16,
18,
19, // right
20,
21,
22,
20,
22,
23, // left
];
//Defining colors for the color buffer
const colors = [
1.0,1.0,1.0, //white color
1.0,0.0,0.0, //red color
0.0,1.0,0.0, //green color
0.0,0.0,1.0, //blue color
0.0,0.0,0.0, // black color
1.0,1.0,1.0, //white color
1.0,0.0,0.0, //red color
0.0,1.0,0.0, //green color
0.0,0.0,1.0, //blue color
0.0,0.0,0.0, // black color
1.0,1.0,1.0, //white color
1.0,0.0,0.0, //red color
0.0,1.0,0.0, //green color
0.0,0.0,1.0, //blue color
0.0,0.0,0.0, // black color
1.0,1.0,1.0, //white color
1.0,0.0,0.0, //red color
0.0,1.0,0.0, //green color
0.0,0.0,1.0, //blue color
0.0,0.0,0.0, // black color
1.0,0.0,0.0, //red color
0.0,1.0,0.0, //green color
0.0,0.0,1.0, //blue color
0.0,0.0,0.0, // black color
];
var angle = 0;
function main() {
var canvas = document.getElementById('canvas');
var gl = canvas.getContext('webgl');
if (!gl) {
console.log('Your browser does not support WebGL');
}
// Initializing shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var n = initBuffers(gl,boxVertices,boxIndices,colors);
var matWorldUniformLocation = gl.getUniformLocation(gl.program, 'mWorld');
checkLocations(matWorldUniformLocation);
var matViewUniformLocation = gl.getUniformLocation(gl.program, 'mView');
checkLocations(matViewUniformLocation);
var matProjUniformLocation = gl.getUniformLocation(gl.program, 'mProj');
checkLocations(matProjUniformLocation);
var worldMatrix = mat4.create();
var viewMatrix = mat4.create();
var projMatrix = mat4.create();
mat4.lookAt(viewMatrix, [3, 3, 7], //x,y,z
[0, 0, 0], [0, 1, 0]);
mat4.perspective(projMatrix, glMatrix.toRadian(20), 1/1, 1, 100);
gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, worldMatrix);
gl.uniformMatrix4fv(matViewUniformLocation, gl.FALSE, viewMatrix);
gl.uniformMatrix4fv(matProjUniformLocation, gl.FALSE, projMatrix);
var xRotationMatrix = mat4.create();
var yRotationMatrix = mat4.create();
var identityMatrix = mat4.create();
function loop() {
angle = performance.now() / 1000 / 6 * 2 * Math.PI;
mat4.rotate(yRotationMatrix, identityMatrix, angle, [0, 1, 0]);
mat4.rotate(xRotationMatrix, identityMatrix, angle / 4, [1, 0, 0]);
mat4.mul(worldMatrix, yRotationMatrix, xRotationMatrix);
gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, worldMatrix);
gl.clearColor(0.5, 0.5, 0.5, 0.8);
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
};
function checkLocations(location){
if(!location){
console.log("ERROR: cannot find storage location of " + location);
}
}
function initBuffers(gl,boxVertices,boxIndices,colors){
const boxVertexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, boxVertexBufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(boxVertices), gl.STATIC_DRAW);
const boxIndexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boxIndexBufferObject);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(boxIndices), gl.STATIC_DRAW);
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors),gl.STATIC_DRAW);
var positionAttribLocation = gl.getAttribLocation(gl.program, 'vertPosition');
var colorAttribLocation = gl.getAttribLocation(gl.program, 'vertColor');
gl.vertexAttribPointer(positionAttribLocation, // Attribute location
3, // Number of elements per attribute
gl.FLOAT, // Type of elements
gl.FALSE,
0, // Size of an individual vertex
0 // Offset from the beginning of a single vertex to this attribute
);
gl.vertexAttribPointer(
colorAttribLocation, // Attribute location
3, // Number of elements per attribute
gl.FLOAT, // Type of elements
gl.FALSE,
0,
0
);
gl.enableVertexAttribArray(positionAttribLocation);
gl.enableVertexAttribArray(colorAttribLocation);
// Tell OpenGL state machine which program should be active.
gl.useProgram(gl.program);
var n = boxIndices.length;
return n;
}
当您调用
vertexAttribPointer
时,它会从当前绑定的gl.ARRAY_BUFFER
中读取数据。
在你的代码中你应该绑定你的
boxVertexBufferObject
缓冲区然后调用相应的gl.vertexAttribPointer(positionAttribLocation...
.
然后你应该绑定你的
colorBuffer
,然后调用相应的gl.vertexAttribPointer(colorAttribLocation...
。
您的代码中的错误是您绑定了
boxVertexBufferObject
缓冲区,然后在调用 colorBuffer
之前绑定了 gl.vertexAttribPointer
,有效地覆盖了您需要加载的数据。结果是 colorBuffer
被加载到 vertPosition
和 vertColor
属性中,这就是为什么你的脸加载不正确。这些面使用 colorBuffer
值作为顶点而不是 boxIndices
值。
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas"></canvas>
</body>
<script type="module">
import { glMatrix, mat4 } from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm'
window.mat4 = mat4;
console.log(mat4)
//Defing Vector shader
var VSHADER_SOURCE =
'precision mediump float;\n ' +
'attribute vec3 vertPosition;\n ' +
'attribute vec3 vertColor;\n ' +
'uniform mat4 mWorld;\n ' +
'uniform mat4 mView;\n ' +
'uniform mat4 mProj;\n ' +
'varying vec3 vColor;\n ' +
'void main()\n ' +
'{\n ' +
' vColor = vertColor;\n ' +
' gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);\n ' +
'}'
//Defining Fragment Shader
var FSHADER_SOURCE =
'precision mediump float;\n ' +
'varying vec3 vColor;\n ' +
'void main()\n ' +
'{\n ' +
' gl_FragColor = vec4(vColor, 1.0);\n ' +
'}';
//Defining vertices for rectangular cube
var boxVertices =
[ // X, Y, Z
// Front face
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// Back face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// Top face
-1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
// Bottom face
-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
// Right face
1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0,
// Left face
-1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0,
];
//Defining indices for rectangular cube
var boxIndices =
[
0,
1,
2,
0,
2,
3, // front
4,
5,
6,
4,
6,
7, // back
8,
9,
10,
8,
10,
11, // top
12,
13,
14,
12,
14,
15, // bottom
16,
17,
18,
16,
18,
19, // right
20,
21,
22,
20,
22,
23, // left
];
//Defining indices for rectangular cube
// var boxIndices =
// [
// 0,
// 1,
// 2,
// // 7,
// // 8,
// // 9,
// 4,
// 5,
// 6
// ];
//Defining colors for the color buffer
const colors = [
1.0, 1.0, 1.0, //white color
1.0, 0.0, 0.0, //red color
0.0, 1.0, 0.0, //green color
0.0, 0.0, 1.0, //blue color
0.0, 0.0, 0.0, // black color
1.0, 1.0, 1.0, //white color
1.0, 0.0, 0.0, //red color
0.0, 1.0, 0.0, //green color
0.0, 0.0, 1.0, //blue color
0.0, 0.0, 0.0, // black color
1.0, 1.0, 1.0, //white color
1.0, 0.0, 0.0, //red color
0.0, 1.0, 0.0, //green color
0.0, 0.0, 1.0, //blue color
0.0, 0.0, 0.0, // black color
1.0, 1.0, 1.0, //white color
1.0, 0.0, 0.0, //red color
0.0, 1.0, 0.0, //green color
0.0, 0.0, 1.0, //blue color
0.0, 0.0, 0.0, // black color
1.0, 0.0, 0.0, //red color
0.0, 1.0, 0.0, //green color
0.0, 0.0, 1.0, //blue color
0.0, 0.0, 0.0, // black color
];
var angle = 0;
function initShaders(gl, vertexSource, fragmentSource) {
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.validateProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('Link failed: ' + gl.getProgramInfoLog(program));
console.error('vs info-log: ' + gl.getShaderInfoLog(vertexShader));
console.error('fs info-log: ' + gl.getShaderInfoLog(fragmentShader));
}
gl.useProgram(program);
gl.program = program;
return program;
}
function main() {
var canvas = document.getElementById('canvas');
var gl = canvas.getContext('webgl');
if (!gl) {
console.log('Your browser does not support WebGL');
}
// Initializing shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var n = initBuffers(gl, boxVertices, boxIndices, colors);
var matWorldUniformLocation = gl.getUniformLocation(gl.program, 'mWorld');
checkLocations(matWorldUniformLocation);
var matViewUniformLocation = gl.getUniformLocation(gl.program, 'mView');
checkLocations(matViewUniformLocation);
var matProjUniformLocation = gl.getUniformLocation(gl.program, 'mProj');
checkLocations(matProjUniformLocation);
var worldMatrix = mat4.create();
var viewMatrix = mat4.create();
var projMatrix = mat4.create();
mat4.lookAt(viewMatrix, [3, 3, 7], //x,y,z
[0, 0, 0], [0, 1, 0]);
mat4.perspective(projMatrix, glMatrix.toRadian(20), 1 / 1, 1, 100);
gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, worldMatrix);
gl.uniformMatrix4fv(matViewUniformLocation, gl.FALSE, viewMatrix);
gl.uniformMatrix4fv(matProjUniformLocation, gl.FALSE, projMatrix);
var xRotationMatrix = mat4.create();
var yRotationMatrix = mat4.create();
var identityMatrix = mat4.create();
function loop() {
angle = performance.now() / 1000 / 6 * 2 * Math.PI;
mat4.rotate(yRotationMatrix, identityMatrix, angle, [0, 1, 0]);
mat4.rotate(xRotationMatrix, identityMatrix, angle / 4, [1, 0, 0]);
mat4.mul(worldMatrix, yRotationMatrix, xRotationMatrix);
gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, worldMatrix);
gl.clearColor(0.5, 0.5, 0.5, 0.8);
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, boxIndices.length, gl.UNSIGNED_SHORT, 0);
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
};
function checkLocations(location) {
if (!location) {
console.log("ERROR: cannot find storage location of " + location);
}
}
function initBuffers(gl, boxVertices, boxIndices, colors) {
gl.useProgram(gl.program);
var positionAttribLocation = gl.getAttribLocation(gl.program, 'vertPosition');
var colorAttribLocation = gl.getAttribLocation(gl.program, 'vertColor');
gl.enableVertexAttribArray(positionAttribLocation);
gl.enableVertexAttribArray(colorAttribLocation);
const boxVertexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, boxVertexBufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(boxVertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(positionAttribLocation, // Attribute location
3, // Number of elements per attribute
gl.FLOAT, // Type of elements
false,
0, // Size of an individual vertex
0 // Offset from the beginning of a single vertex to this attribute
);
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
gl.vertexAttribPointer(
colorAttribLocation, // Attribute location
3, // Number of elements per attribute
gl.FLOAT, // Type of elements
false,
0,
0
);
const boxIndexBufferObject = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boxIndexBufferObject);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(boxIndices), gl.STATIC_DRAW);
// Tell OpenGL state machine which program should be active.
var n = boxIndices.length;
return n;
}
main();
</script>
</html>