在webgl中绘制一个简单的正方形



我有一个非常基本的问题。我是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.multiplyVec3mat4.multiplyVec4混淆。vertex的第四个组成部分应设置为乘法前的1;这样,GPU 可以使用transformedVertex的第四个分量来执行透视除法(这会自动发生,但您需要发送正确的值)。

    另请注意,如果您错误地将vec3属性发送到 GPU,并且该属性实际上是 vec4 类型,则第 4 个组件默认为 1.0。这通常很方便,但如果在 JavaScript 中预乘这些值,也可能导致棘手的错误。正如 John 所说,尽量保持着色器定义与 JavaScript 端一致;从长远来看,这将减少混乱。

最新更新