gpt4 book ai didi

opengl - glVertexAttribPointer 澄清

转载 作者:行者123 更新时间:2023-12-03 04:58:38 30 4
gpt4 key购买 nike

只是想确保我正确理解这一点(我会在 SO Chat 上问,但它已经死在那里了!):

我们有一个顶点数组,我们通过绑定(bind)它使其成为“当前”
然后我们有一个缓冲区,我们将其绑定(bind)到目标
然后我们通过 glBufferData 填充该目标
它基本上填充了绑定(bind)到该目标的任何内容,即我们的缓冲区
然后我们打电话glVertexAttribPointer它描述了数据的布局方式——数据是绑定(bind)到 GL_ARRAY_BUFFER 的任何内容。
并且这个描述符被保存到我们原来的顶点数组中

(1)我的理解正确吗?
documentation关于一切如何关联的内容有点稀疏。

(2) 是否有某种默认的顶点数组?因为我忘记/省略了glGenVertexArraysglBindVertexArray没有它,我的程序运行良好。

编辑:我错过了一步... glEnableVertexAttribArray .

(3)当时的Vertex Attrib是否绑定(bind)到Vertex Array glVertexAttribPointer被调用,然后我们可以通过 glEnableVertexAttribArray 启用/禁用该属性在任何时候,无论当前绑定(bind)的是哪个顶点数组?

或 (3b) 顶点属性是否与当时的顶点数组相关联 glEnableVertexAttribArray被调用,因此我们可以通过调用 glEnableVertexAttribArray 将相同的顶点属性添加到多个顶点数组中。在不同的时间,何时绑定(bind)不同的顶点数组?

最佳答案

一些术语有点偏离:

  • 一个 Vertex Array只是一个包含顶点数据的数组(通常是 float[] )。它不需要绑定(bind)到任何东西。不要与 Vertex Array Object 混淆或 VAO,我稍后会介绍
  • 一个 Buffer Object ,通常称为 Vertex Buffer Object存储顶点时,或简称 VBO,就是您所说的 Buffer .
  • 没有任何东西被保存回顶点数组,glVertexAttribPointer工作原理与 glVertexPointer 完全一样或 glTexCoordPointer工作,只是代替命名属性,您可以提供一个数字来指定您自己的属性。您将此值传递为 index .所有您的 glVertexAttribPointer下次您拨打 glDrawArrays 时,电话将排队等候或 glDrawElements .如果您绑定(bind)了 VAO,VAO 将存储您所有属性的设置。

  • 这里的主要问题是您将顶点属性与 VAO 混淆了。顶点属性只是为绘图定义顶点、texcoords、法线等的新方法。 VAO 存储状态。我将首先解释如何使用顶点属性进行绘图,然后解释如何使用 VAO 减少方法调用的数量:
  • 您必须先启用一个属性,然后才能在着色器中使用它。例如,如果您想将顶点发送到着色器,您很可能会将其作为第一个属性 0 发送。因此,在渲染之前,您需要使用 glEnableVertexAttribArray(0); 启用它。 .
  • 现在启用了一个属性,您需要定义它要使用的数据。为此,您需要绑定(bind)您的 VBO - glBindBuffer(GL_ARRAY_BUFFER, myBuffer); .
  • 现在我们可以定义属性 - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); .按参数顺序:0 是你定义的属性,3 是每个顶点的大小,GL_FLOAT是类型,GL_FALSE意味着不对每个顶点进行归一化,最后 2 个零意味着顶点上没有步幅或偏移。
  • 用它画一些东西 - glDrawArrays(GL_TRIANGLES, 0, 6);
  • 接下来你绘制的东西可能不会使用属性 0(实际上它会,但这是一个例子),所以我们可以禁用它 - glDisableVertexAttribArray(0);

  • 将其包裹在 glUseProgram() 中调用,并且您有一个可以正确使用着色器的渲染系统。但是假设您有 5 个不同的属性,顶点、texcoords、法线、颜色和光照贴图坐标。首先,您将制作一个 glVertexAttribPointer调用这些属性中的每一个,并且您必须事先启用所有属性。假设您按照我列出的方式定义属性 0-4。您可以像这样启用所有这些:
    for (int i = 0; i < 5; i++)
    glEnableVertexAttribArray(i);

    然后您必须为每个属性绑定(bind)不同的 VBO(除非您将它们全部存储在一个 VBO 中并使用偏移量/步幅),那么您需要制作 5 个不同的 glVertexAttribPointer来电,来自 glVertexAttribPointer(0,...);glVertexAttribPointer(4,...);分别用于顶点到光照贴图坐标。

    希望这个系统本身就有意义。现在我将转到 VAO 来解释如何使用它们来减少进行此类渲染时的方法调用次数。请注意,没有必要使用 VAO。

    一个 Vertex Array Object或 VAO 用于存储所有 glVertexAttribPointer 的状态当 glVertexAttribPointer 中的每一个时,调用和目标 VBO打了电话。

    您通过拨打 glGenVertexArrays 生成一个.要将您需要的所有内容存储在 VAO 中,请将其绑定(bind) glBindVertexArray ,然后进行完整的绘制调用。所有的绘制绑定(bind)调用都会被 VAO 拦截和存储。您可以使用 glBindVertexArray(0); 解除绑定(bind) VAO

    现在当你想绘制对象时,你不需要重新调用所有的 VBO 绑定(bind)或 glVertexAttribPointer调用,你只需要绑定(bind) VAO 与 glBindVertexArray然后拨打 glDrawArraysglDrawElements并且您将绘制完全相同的内容,就像您进行所有这些方法调用一样。之后您可能也想解除绑定(bind) VAO。

    解除绑定(bind) VAO 后,所有状态都会恢复到绑定(bind) VAO 之前的状态。我不确定您在绑定(bind) VAO 时所做的任何更改是否保留,但这可以通过测试程序轻松解决。我猜你能想到 glBindVertexArray(0);作为绑定(bind)到“默认”VAO ...

    更新:有人让我注意到实际绘制调用的必要性。事实证明,在设置 VAO 时,您实际上并不需要进行完整的绘制调用,只需进行所有绑定(bind)即可。不知道为什么我之前认为这是必要的,但现在已经解决了。

    关于opengl - glVertexAttribPointer 澄清,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8704801/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com