Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl 如何将模型矩阵包含到VBO中?_Opengl_Opengl Es_Webgl_Vbo_Vertex Buffer - Fatal编程技术网

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

Opengl 如何将模型矩阵包含到VBO中?,opengl,opengl-es,webgl,vbo,vertex-buffer,Opengl,Opengl Es,Webgl,Vbo,Vertex Buffer,我想发送一个缓冲区列表(到GPU/顶点着色器),其中包含有关顶点位置、世界位置、颜色、比例和旋转的信息 如果我的每个3D对象在矩阵中都有与变换相关的信息,如何通过VBO将此矩阵阵列(以及其他顶点数据)传递到GPU 已更新 请原谅任何打字错误: // bind & set vertices. gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.vertexAtribPointer(a_Position, 3, gl.FLOAT, false,

我想发送一个缓冲区列表(到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);

请注意,这些缓冲区(
vertexBuffer
vertexNormalsBuffer
WorldPositionBuffer
vertexIndexBuffer
)是我的场景中所有相应3D对象的串联(这是我通过属性/制服一个接一个地渲染的——这是一种简单得多、更容易掌握的天真方法,但对于1000个对象来说速度非常慢).

对于渲染帧时需要频繁更改的任何值,将其作为
属性
而不是
统一属性
传递到着色器中会更有效。这还有一个优点,即如果您选择,可以将值存储在VBO中。请注意,不需要在VBO中存储属性,它们可以也可以使用
glVertexAttrib[1234]f()或
glVertexAttrib[1234]fv()指定

这适用于变换矩阵,就像传递到着色器中的任何其他值一样。如果它变化非常频繁,您可能应该将其作为属性。在这种情况下,唯一的细微之处是我们处理的是矩阵,属性必须是向量。但这很容易克服。通常作为
mat4可由3个
vec4
类型的值表示,其中这3个向量是矩阵的列向量。当然,4个向量表示完全通用的4x4矩阵,但变换矩阵中的第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);

第二次draw调用比第二次draw调用对CPU的负担要小得多(您自己试试)。这是因为两次draw调用之间没有状态更改。如果您只是在draw调用之间更新模型矩阵统一变量,那么这不会显著增加成本。这是可能的(并且是推荐的)通过按着色器程序和材质对对象进行排序来最小化状态更改。

通常,可以统一设置模型矩阵并在模型之间进行更改。我拥有平移、旋转和缩放(均包含在模型矩阵中)不同的3d对象所以我认为每个物体都有各自的模型矩阵。但是每个模型都有很多三角形,所以只需为第一个模型设置统一的模型矩阵,绘制第一个模型的三角形为第二个模型设置模型矩阵,绘制第二个模型的三角形,我想我需要澄清一下,因为你解释的就是我的意思正在进行(但速度非常慢)。现在我正在尝试使用VBO(s)进行单次绘制调用。因此,我所有的顶点信息都在单顶点缓冲区中(例如,对于1000的三角形)。您是否出于某种奇怪的未知原因,试图为正在绘制的每个三角形都创建一个矩阵?为什么这样会更有效?现在您需要更新网格中每个顶点的变换向量,而不是单个均匀点。这似乎也是一个巨大的内存浪费,对于详细的m来说,这可能会很快累积起来eshes。您所指的是(静态)批处理。您只能在对象不移动的情况下执行此操作。在这种情况下,您只需修改顶点位置,以减少绘制调用(不需要矩阵/向量)。请注意,draw调用本身并不昂贵。昂贵的是状态更改。状态更改将推迟到您进行draw调用。如果您的对象不是静态的,那么我看不出您如何从上述方法中获益。@Homar:提出的问题是如何在VBO中拥有转换矩阵。这就是我的答案。我认为,如果不实施至少4或5种不同的方法,不在各种平台上进行比较,就不可能知道OP用例的最快解决方案是什么。但这个网站的想法实际上是为了回答特定的问题。@Homar,在你最后的评论中:虽然我没有使用WebGL,但我相信实例渲染不是最快的支持那里,因为它是基于ES 2.0的。有al