繁体   English   中英

如何将模型矩阵包括到VBO中?

[英]How to include model matrix to a VBO?

我想发送一个缓冲区列表(到GPU /顶点着色器),其中包含有关顶点位置,世界位置,颜色,比例和旋转的信息。

如果我的每个3D对象在矩阵中都具有与转换有关的信息,我如何通过VBO将这个矩阵数组(除了其他顶点数据之外)传递给GPU?

已更新请原谅任何错别字:

// bind & set vertices.
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAtribPointer(a_Position, 3, gl.FLOAT, false, stride, 0);

// bind & set vertex normals.
gl.bindBuffer(gl.ARRAY_BUFFER,, vertexNormalsBuffer);
gl.vertexAttribPointer(a_Normal, 3, gl.FLOAT, false, stride, 0);

// becaue i cant pass in a model matrix via VBO, im tryng to pass in my world coordinates.
gl.bindBuffer(gl.ARRAY_BUFFER, worldPositionBuffer);

// not sure why i need to do this, but most tutorials i've read says to do this.
gl.bindBuffer(gl.ARRAY_BUFFER, null);

// bind & draw index buffer.
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, vertexIndexCount, gl.UNSIGNED_SHORT, 0);

请注意,这些缓冲区( vertexBuffervertexNormalsBufferworldPostiionBuffervertexIndexBuffer )是场景中所有各个3D对象的串联(我通过属性/制服来逐一渲染-天真的方法更容易实现掌握,但对于1000个对象却非常慢)。

对于在渲染框架时需要经常更改的任何值,将它们作为attribute而不是uniform传递到着色器中会更有效。 这还具有以下优点:您可以选择将值存储在VBO中。 请注意, 不需要将属性存储在VBO中,也可以使用glVertexAttrib[1234]f()glVertexAttrib[1234]fv()来指定属性。

与传递到着色器中的任何其他值一样,这也适用于变换矩阵。 如果更改非常频繁,则可能应将其设置为属性。 在这种情况下,唯一的轻微折痕是我们正在处理矩阵,并且属性必须是向量。 但这很容易克服。 通常作为mat4传入的内容可以由vec4类型的3个值表示,其中这3个向量是矩阵的列向量。 代表一个完全通用的4x4矩阵当然是4个向量,但是转换矩阵中的第4列不用于任何常见的转换类型(投影矩阵除外)。

如果希望将转换包含在VBO中,则可以设置3个以上的属性,就像您对位置和颜色所做的一样。 您存储在VBO中的属性的值是相应转换矩阵的列向量。

然后,在顶点着色器中,通过计算变换属性向量与输入位置的点积来应用变换。 代码看起来像这样:

attribute vec4 InPosition;
attribute vec4 XTransform;
attribute vec4 YTransform;
attribute vec4 ZTransform;
main() {
    vec3 eyePosition = vec3(
        dot(XTransform, InPosition),
        dot(YTransform, InPosition),
        dot(ZTransform, InPosition));
    ...
}

还有其他方法可以在完全OpenGL中解决此问题,例如使用统一缓冲区对象。 但是对于WebGL和OpenGL ES 2.0,我认为这是最好的解决方案。

您的方法是正确的,并且在某种程度上是不可避免的。 如果您有1000个非静态的 不同对象,则需要(或最好)进行1000次绘制调用。 但是,如果您的对象是静态的,则可以将它们合并在一起,只要它们使用相同的材​​质即可。

合并静态对象很简单。 您可以通过乘以模型矩阵来修改顶点位置,以将顶点转换为世界空间。 然后,您可以在一个绘制调用中渲染批处理。

如果同一对象的许多实例具有不同的模型矩阵(即不同的位置,方向或比例),则应使用实例渲染。 这将允许您在一个绘制调用中渲染所有实例。

最后,请注意,绘制调用不一定很昂贵。 发生的情况是状态更改被推迟到发出抽奖电话为止。 例如,考虑以下内容:

gl.drawElements(gl.TRIANGLES, vertexIndexCount, gl.UNSIGNED_SHORT, 0);
gl.drawElements(gl.TRIANGLES, vertexIndexCount, gl.UNSIGNED_SHORT, 0);

第二次抽奖将比第二次抽奖对CPU的负担少得多(亲自尝试)。 这是因为两个绘图调用之间没有状态更改。 如果您只是在绘制调用之间更新模型矩阵统一变量,则不会显着增加成本。 可以(并建议)通过按着色器程序和材质对对象进行排序来最小化状态更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM