0

我有一个非常基本的问题。我是 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 中的模型视图和透视矩阵相乘,然后将修改后的顶点传递给着色器,它似乎不起作用。

我无法发现错误。帮助高度赞赏!

4

2 回答 2

2

马上我注意到几个问题:

1)您的顶点着色器输入属性与传递给vertexAttribPointer的参数不匹配:

您指定该属性为 4 个浮点宽,但您的顶点着色器将其指定为 vec3。这些应该是一致的。

2) 我没有看到对 enableVertexAttribArray 的调用,例如:

gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

您必须启用顶点着色器使用的顶点属性数组。

3)从显示的代码中 - 您只指定一个模型矩阵(身份,翻译)。您需要创建一个视图矩阵。一个简单的方法是调用 mat4.lookAt。它有以下定义:

mat4.lookAt = function (eye, center, up, dest)

eye 是相机的位置 center 是相机向上看的位置 应该始终是 (0, 1, 0)

一个例子是:

眼睛 = (0, 0, 1) 中心 = (0, 0, 0)

这将相机 1 单元放在 Z 轴正方向下方,并让它看着原点。

将此与您的模型矩阵相乘将为您提供模型视图矩阵。


缺少太多代码,因此很难确定您的错误是否出在其他地方。例如,您的片段着色器是做什么的?


当尝试在屏幕上显示您的第一个图元时,我建议禁用剔除和深度测试。如果您的片段输出与透明颜色匹配,请随着时间的推移改变您的透明颜色。

约翰

于 2012-08-17T14:37:51.390 回答
1

约翰的回答中概述的问题值得研究,但如果您现在要正确渲染原语,那么我认为它们不是这个问题的根本原因。

由于我不确定哪种情况适用于您,因此我将答案分为两部分:

  • 您没有展示如何构建 MVP 的 JavaScript 版本,但请仔细检查您的乘法语法是否正确。它应该是以下形式:

    mat4.multiply(p, mv, mvp);
    

    其中p是投影矩阵,mv是模型视图矩阵,mvp是接收模型视图投影矩阵(将存储结果)。

  • 同样,如果您自己预乘顶点位置,正确的语法是:

    mat4.multiplyVec4(mvp, vertex, transformedVertex);
    

    其中mvp是模型视图投影矩阵,vertex是未修改的顶点 (a vec4),是存储值transformedVertex的接收。vec4如果使用这种方法,则必须先将顶点数组展平为单个连续的浮点数组,然后再将它们发送到 GPU。

    注意不要mat4.multiplyVec3mat4.multiplyVec4. 的第四个分量vertex应该设置1在乘法之前;这样,transformedVertexGPU 可以使用 的第四个组件来执行透视分割(这会自动发生,但您需要发送正确的值)。

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

于 2012-08-17T15:09:44.967 回答