OpenGL 多少个 VAO [英] OpenGL How Many VAOs

查看:55
本文介绍了OpenGL 多少个 VAO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 OpenGL3+ 应用程序,但对 VAO 的使用有些困惑.现在我只有一个 VAO,一个围绕原点的标准化四边形集.这个单一的 VAO 包含 3 个 VBO;一个用于位置,一个用于表面法线,一个 GL_ELEMENT_ARRAY_BUFFER 用于索引(因此我只能存储 4 个顶点,而不是 6 个).

I am writing an OpenGL3+ application and have some confusion about the use of VAOs. Right now I just have one VAO, a normalised quad set around the origin. This single VAO contains 3 VBOs; one for positions, one for surface normals, and one GL_ELEMENT_ARRAY_BUFFER for indexing (so I can store just 4 vertices, rather than 6).

我已经设置了一些辅助方法来将对象绘制到场景中,例如 drawCube() 它接受位置和旋转值并遵循程序;

I have set up some helper methods to draw objects to the scene, such as drawCube() which takes position and rotation values and follows the procedure;

  • 绑定quad VAO.
  • 每个立方体面:
    • 创建代表这张脸的模型矩阵.
    • 将模型矩阵上传到 uniform mat4 model 顶点着色器变量.
    • 调用 glDrawElements() 将四边形绘制到该面的位置.
    • Bind the quad VAO.
    • Per cube face:
      • Create a model matrix that represents this face.
      • Upload the model matrix to the uniform mat4 model vertex shader variable.
      • Call glDrawElements() to draw the quad into the position for this face.

      我刚刚开始添加每个立方体颜色的任务,并意识到我不能将我的颜色 VBO 添加到单个 VAO 中,因为它会随着每个立方体而变化,这感觉不对.

      I have just set about the task of adding per-cube colors and realised that I can't add my color VBO to the single VAO as it will change with each cube, and this doesn't feel right.

      我刚刚阅读了问题;OpenGL VAO 最佳实践,它告诉我我的方法是错误的,我应该使用更多VAO 节省了每次设置整个场景的工作.

      I have just read the question; OpenGL VAO best practices, which tells me that my approach is wrong, and that I should use more VAOs to save the work of setting the whole scene up every time.

      应该使用多少个 VAO? 很明显,我使用 1 的方法不是最佳的,是否应该为场景中的每个静态表面都有一个 VAO?那些会动的呢?

      How many VAOs should be used? Clearly my approach of having 1 is not optimal, should there be a VAO for every static surface in the scene? What about ones that move?

      我正在为每个顶点写入一个统一变量,这是正确的吗?我读到 uniform 着色器变量不应在中间帧中改变,如果我能够将不同的值写入我的 uniform 变量,uniform 与顶点着色器中的简单 in 变量有何不同?

      I am writing to a uniform variable for each vertex, is that correct? I read that uniform shader variables should not change mid-frame, if I am able to write different values to my uniform variable, how do uniforms differ from simple in variables in a vertex shader?

      推荐答案

      显然我的方法是 1 不是最佳的,场景中的每个静态表面都应该有一个 VAO 吗?

      Clearly my approach of having 1 is not optimal, should there be a VAO for every static surface in the scene?

      绝对不是.切换 VAO 的成本很高.如果您为场景中的每个对象分配一个 VAO,则需要在渲染此类对象之前切换 VAO.将其扩展到当前可见的数百或数千个对象,您将获得同样多的 VAO 更改.问题是,如果您有多个共享公共内存布局的对象,即元素的大小/类型/规范化/步幅相同,为什么要定义多个都存储相同信息的 VAO?您可以使用相应的绘制调用直接控制要从何处开始拉取顶点属性的偏移量.

      Absolutely not. Switching VAOs is costly. If you allocate one VAO per object in your scene, you need to switch the VAO before rendering such objects. Scale that up to a few hundred or thousand objects currently visible and you get just as much VAO changes. The questions is, if you have multiple objects which share a common memory layout, i.e. sizes/types/normalization/strides of elements are the same, why would you want to define multiple VAOs that all store the same information? You control the offset where you want to start pulling vertex attributes from directly with a corresponding draw call.

      对于非索引几何,这是微不足道的,因为您向 gl[Multi]DrawArrays*() 提供了一个 first(或在多次绘制情况下的偏移数组)参数,它定义了偏移到关联的 ARRAY_BUFFER 的数据存储中.

      For non-indexed geometry this is trivial, since you provide a first (or an array of offsets in the multi-draw case) argument to gl[Multi]DrawArrays*() which defines the offset into the associated ARRAY_BUFFER's data store.

      对于索引几何,如果您在单个 ELEMENT_ARRAY_BUFFER 中存储多个对象的索引,您可以使用 gl[Multi]DrawElementsBaseVertex 为索引提供恒定偏移量或通过在将它们上传到缓冲对象.

      For indexed geometry, and if you store indices for multiple objects in a single ELEMENT_ARRAY_BUFFER, you can use gl[Multi]DrawElementsBaseVertex to provide a constant offset for indices or manually offset your indices by adding a constant offset before uploading them to the buffer object.

      能够为缓冲存储提供偏移量还意味着您可以在单个 ARRAY_BUFFER 中存储多个不同的对象,在单个 ELEMENT_ARRAY_BUFFER 中存储相应的索引.但是,缓冲区对象应该有多大取决于您的硬件和供应商的建议不同.

      Being able to provide offsets into a buffer store also implies that you can store multiple distinct objects in a single ARRAY_BUFFER and corresponding indices in a single ELEMENT_ARRAY_BUFFER. However, how large buffer objects should be depends on your hardware and vendors differ in their recommendations.

      我正在为每个顶点写入一个统一变量,对吗?我读到统一着色器变量不应在中间帧中更改,如果我能够将不同的值写入统一变量,统一着色器与顶点着色器中的简单变量有何不同?

      I am writing to a uniform variable for each vertex, is that correct? I read that uniform shader variables should not change mid-frame, if I am able to write different values to my uniform variable, how do uniforms differ from simple in variables in a vertex shader?

      首先,声明为in/out的uniforms和着色器输入/输出变量在各种情况下是不同的:

      First of all, a uniforms and shader input/output variables declared as in/out differ in various instances:

      • 输入/输出变量定义了着色器阶段之间的接口,即一个着色器阶段中的输出变量由下一阶段中相应且同名的输入变量支持.如果使用相同的名称声明,则统一在所有阶段都可用,并且在应用程序更改之前保持不变.

      • input/output variables define an interface between shader stages, i.e. output variables in one shader stage are backed by a corresponding and equally named input variable in the following stage. A uniform is available in all stages if declared with the same name and is constant until changed by the application.

      顶点着色器内的输入变量由 ARRAY_BUFFER 填充.统一块内的统一由 UNIFORM_BUFFER 支持.

      input variables inside a vertex shader are filled from an ARRAY_BUFFER. Uniforms inside a uniform block are backed a UNIFORM_BUFFER.

      输入变量也可以直接使用 glVertexAttrib*() 系列函数编写.单个制服是使用 glUniform*() 系列函数编写的.

      input variables can also be written directly using the glVertexAttrib*() family of functions. single uniforms are written using the glUniform*() family of functions.

      制服的价值是程序状态.输入变量的值不是.

      the values of uniforms are program state. the values of input variables are not.

      语义差异也应该很明显:uniforms,顾名思义,在一组基元中通常是恒定的,而输入变量通常每个顶点或片段(由于插值)而变化.

      The semantic difference should also be obvious: uniforms, as their name suggests, are usually constant among a set of primitives, whereas input variables usually change per vertex or fragment (due to interpolation).

      编辑:澄清并考虑 Nicol Bolas 的评论:应用程序不能更改由单个绘制调用提交的一组顶点的制服,也不能通过调用 glVertexAttrib* 来更改顶点属性().由缓冲区对象支持的顶点着色器输入将更改每个顶点一次或以 glVertexAttribDivisor 设置的某个特定速率更改.

      EDIT: To clarify and to factor in Nicol Bolas' remark: Uniforms cannot be changed by the application for a set of vertices submitted by a single draw call, neither can vertex attributes by calling glVertexAttrib*(). Vertex shader inputs backed by a buffer objects will change either once per vertex or at some specific rate set by glVertexAttribDivisor.

      EDIT2:为了阐明 VAO 理论上如何存储多个布局,您可以简单地定义多个具有不同索引但语义相同的数组.例如,

      EDIT2: To clarify how a VAO can theoretically store multiple layouts, you can simply define multiple arrays with different indices but equal semantics. For instance,

      glVertexAttribPointer(0, 4, ....);
      

      glVertexAttribPointer(1, 3, ....);
      

      可以定义两个索引为 0 和 1,组件大小为 3 和 4 的数组,并且都引用顶点的位置属性.但是,根据您要渲染的内容,您可以绑定一个假设的顶点着色器输入

      could define two arrays with indices 0 and 1, component sized 3 and 4 and both refer to position attributes of vertices. However, depending on what you want to render, you can bind a hypothetical vertex shader input

      // if you have GL_ARB_explicit_attrib_location or GL3.3 available, use explicit
      // locations
      /*layout(location = 0)*/ in vec4 Position; 
      

      /*layout(location = 1)*/ in vec3 Position;
      

      显式索引 0 或 1 或 glBindAttribLocation() 并仍然使用相同的 VAO.AFAIK,规范没有说明如果一个属性被启用但不是由当前着色器提供会发生什么,但我怀疑在这种情况下实现简单地忽略该属性.

      to either index 0 or 1 explicitly or glBindAttribLocation() and still use the same VAO. AFAIK, the spec says nothing about what happens if an attribute is enabled but not sourced by the current shader but I suspect implementation to simply ignore the attribute in that case.

      您是否从相同或不同的缓冲区对象中获取所述属性的数据是另一个问题,但当然可能.

      Whether you source the data for said attributes from the same or a different buffer object is another question but of course possible.

      我个人倾向于在每个布局中使用一个 VBO 和 VAO,即如果我的数据由相同数量的具有相同属性的属性组成,我会将它们放入一个 VBO 和一个 VAO.

      Personally I tend to use one VBO and VAO per layout, i.e. if my data is made up of an equal number of attributes with the same properties, I put them into a single VBO and a single VAO.

      一般来说:您可以大量地试验这些东西.做吧!

      In general: You can experiment with this stuff a lot. Do it!

      这篇关于OpenGL 多少个 VAO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆