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

查看:231
本文介绍了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;

  • 绑定方形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?显然我的方法不是最优的,场景中的每个静态表面都应该有一个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变量,统一与顶点着色器中的简单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?

      推荐答案

      显然我的方法不是最优的,场景中的每个静态表面都应该有一个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 的统一和着色器输入/输出变量不同:

      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.

      语义上的区别也应该是显而易见的:顾名思义,制服在一组基元中通常是不变的,而输入变量通常会因顶点或片段而变化(由于插值).

      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.

      通常:您可以大量尝试.做吧!

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

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