【问题标题】:Drawing a simple square in webgl在 webgl 中绘制一个简单的正方形
【发布时间】:2012-08-17 23:09:44
【问题描述】:

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

我无法发现错误。非常感谢您的帮助!

【问题讨论】:

标签: webgl


【解决方案1】:

我马上就注意到了几个问题:

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

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

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

gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

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

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

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

eye 是相机的位置 center 是相机正在看的位置 up 应该总是 (0, 1, 0)

一个例子是:

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

这会将相机 1 个单位沿 Z 轴正方向放置,并使其朝向原点。

将此与您的模型矩阵相乘将得到一个模型视图矩阵。


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


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

约翰

【讨论】:

  • 我们人类使用单独的模型和视图矩阵很方便,但 GL 根本不在乎。在过去,唯一的 GL 矩阵是 ModelView 连接和投影。现在,使用可编程着色器,它没有任何区别。他可以将四元数用于所有 GL 关心;只要正确的值进入gl_Position,一切都很好。就个人而言,我使用单独的模型、视图和投影矩阵进行编程,但尽可能将它们预乘到一个 MVP 中。此外,片段代码对这个问题应该无关紧要,因为它不能改变像素位置。
  • 属性和 vertexAttribPointer 不需要匹配。 GL 为您不提供的任何值提供默认值。 x = 0, y = 0, z = 0, w = 1 默认情况下,因此如果您在代码中使用 vec4 并且仅提供带有 vertexAttribPointer 的 vec3,它将正常工作。
【解决方案2】:

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

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

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

    mat4.multiply(p, mv, mvp);
    

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

  • 类似地,如果你自己预乘顶点位置,正确的语法是:

    mat4.multiplyVec4(mvp, vertex, transformedVertex);
    

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    相关资源
    最近更新 更多