我有一个非常基本的问题。我是webgl的新手,并试图画一个简单的正方形。我正在使用 gl 矩阵库进行矩阵操作。
Javascript 代码:
squareVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
vertices = [
0.9, 0.9, 0.0,1.0,
-0.9, 0.9, 0.0,1.0,
0.9, -0.9, 0.0,1.0,
-0.9, -0.9, 0.0,1.0
];
squareVertexPositionBuffer.itemSize = 4;
squareVertexPositionBuffer.numItems = 4;
mat4.identity(pMatrix);
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [-1.5, 0.0, -7.0]);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
着色:
attribute vec3 aVertexPosition;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec3 debug;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition.xyz, 1.0);
debug = aVertexPosition;
}
这似乎很好。在这里,我将模型视图和透视矩阵作为统一传递给着色器程序,并将它们与那里的顶点坐标相乘。但是,如果在 javascript 中将模型视图和透视矩阵相乘,然后将修改后的顶点传递给着色器,它似乎不起作用。
我无法发现错误。帮助高度赞赏!
注意到几个问题:
1) 您的顶点着色器输入属性与传递给顶点AttribPointer的参数不匹配:
指定属性宽度为 4 个浮点数,但顶点着色器将其指定为 vec3。这些应该是一致的。
2)我没有看到启用VertexAttribArray的调用,如下所示:
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
必须启用顶点着色器使用的顶点属性数组。
3)从显示的代码来看,您只指定了一个模型矩阵(身份,翻译)。您需要创建一个视图矩阵。一个简单的方法是调用mat4.lookAt。它具有以下定义:
mat4.lookAt = 函数(眼睛、中心、向上、目标)
眼睛是相机的位置中心是摄像机正在查看的位置向上应始终为 (0, 1, 0)
一个例子是:
眼睛 = (0, 0, 1)中心 = (0, 0, 0)
这会将相机 1 单元放在正 Z 轴上,并让它查看原点。
将其与模型矩阵相乘将得到模型视图矩阵。
缺少的代码太多,以至于很难确定您的错误是否在其他地方。例如,您的片段着色器有什么作用?
当尝试在屏幕上获取第一个基元时,我建议禁用剔除和深度测试。此外,如果您的片段输出与透明颜色匹配,请随着时间的推移改变您的透明颜色。
John
John 的回答中概述的问题值得研究,但如果你现在让原语正确渲染,那么我认为它们不是这个问题的根本原因。
我将答案分为两部分,因为我不确定哪种情况适用于您:
-
您没有展示如何构建 JavaScript 版本的 MVP,但请仔细检查您的乘法语法是否正确。它的形式应该是:
mat4.multiply(p, mv, mvp);
其中
p
是投影矩阵,mv
是模型视图矩阵,mvp
是接收模型视图投影矩阵(结果将存储在哪里)。 -
同样,如果要对顶点位置本身进行预乘法,则正确的语法是:
mat4.multiplyVec4(mvp, vertex, transformedVertex);
其中
mvp
是 ModelView 投影矩阵,vertex
是未修改的顶点(vec4
),transformedVertex
是将存储值的接收vec4
。如果使用此方法,则必须将顶点数组平展为单个连续的浮点数数组,然后再将它们发送到 GPU。注意不要将
mat4.multiplyVec3
与mat4.multiplyVec4
混淆。vertex
的第四个组成部分应设置为乘法前的1
;这样,GPU 可以使用transformedVertex
的第四个分量来执行透视除法(这会自动发生,但您需要发送正确的值)。另请注意,如果您错误地将
vec3
属性发送到 GPU,并且该属性实际上是vec4
类型,则第 4 个组件默认为 1.0。这通常很方便,但如果在 JavaScript 中预乘这些值,也可能导致棘手的错误。正如 John 所说,尽量保持着色器定义与 JavaScript 端一致;从长远来看,这将减少混乱。