C++ 为什么为一个属性指定不同的顶点格式?

C++ 为什么为一个属性指定不同的顶点格式?,c++,opengl,glsl,C++,Opengl,Glsl,OpenGL函数glVertexAttribPointer和glVertexAttribFormat允许用户指定渲染时绑定到着色器程序中给定属性变量的数据格式。顶点属性格式是数据类型(int、float、字节等)、属性变量中的维度数(vec2、vec3等)、是否应规范化数据以及数据数组起始位置的顶点数组偏移量等信息。这些函数指定构建顶点数组对象(VAO)时的格式,并且指定的格式是VAO状态的一部分。所以我的问题是: 为什么要与属性关联的数据格式是VAO状态的一部分,而不是属性状态的一部分?换句话

OpenGL函数
glVertexAttribPointer
glVertexAttribFormat
允许用户指定渲染时绑定到着色器程序中给定属性变量的数据格式。顶点属性格式是数据类型(
int
float
字节
等)、属性变量中的维度数(
vec2
vec3
等)、是否应规范化数据以及数据数组起始位置的顶点数组偏移量等信息。这些函数指定构建顶点数组对象(VAO)时的格式,并且指定的格式是VAO状态的一部分。所以我的问题是:


为什么要与属性关联的数据格式是VAO状态的一部分,而不是属性状态的一部分?换句话说,为什么数据的格式与VAO关联,而不是与属性关联?在什么情况下,我会有VAO使用不同的格式为同一属性

为了更清楚,这里有一个例子可以说明我为什么感到困惑。想象一下,在我的顶点着色器中,我声明了变量:

in vec3 position;
现在,我在OpenGL应用程序中获取属性位置:

GLint positionAttribute = glGetAttribLocation(myProgram, "position");
现在,当我创建VAO时,我指定如下数据格式:

glVertexAttribFormat(positionAttribute​, 3, GL_FLOAT, GL_FALSE​, 0);

由于格式与VAO关联,因此每次创建VAO时都必须指定格式。“position”属性是
vec3
,因此我将始终指定3和
GL\u FLOAT
glVertexAttribFormat
。那么,为什么OpenGL是这样设计的,以至于每次创建VAO时,我都必须调用
glVertexAttribFormat
,并指定一种保持不变的格式?在我看来,我应该在调用
glGetAttriblLocation
时指定格式,以便只执行一次。

那么,如果有多个属性,会发生什么情况?或者,如果要存储位置、颜色和法线,该怎么办?这在我的经验中特别适用于UV坐标


因为这样,属性的大小将仅为2而不是3。因为你的纹理只有2个坐标(忽略3D纹理的可能性)。如果你是在2D中工作呢。attrib指针允许您为该属性指定输入的大小以及类型。它很有用,因为它允许您更改数据的格式。在任何情况下,您都应该只创建一次VAO,除非您需要将新数据重新绑定到缓冲区。

如果您有多个属性,会发生什么?或者,如果要存储位置、颜色和法线,该怎么办?这在我的经验中特别适用于UV坐标


因为这样,属性的大小将仅为2而不是3。因为你的纹理只有2个坐标(忽略3D纹理的可能性)。如果你是在2D中工作呢。attrib指针允许您为该属性指定输入的大小以及类型。它很有用,因为它允许您更改数据的格式。在任何情况下,您都应该只创建一次VAO,除非您需要将新数据重新绑定到缓冲区。

如果您有多个属性,会发生什么?或者,如果要存储位置、颜色和法线,该怎么办?这在我的经验中特别适用于UV坐标


因为这样,属性的大小将仅为2而不是3。因为你的纹理只有2个坐标(忽略3D纹理的可能性)。如果你是在2D中工作呢。attrib指针允许您为该属性指定输入的大小以及类型。它很有用,因为它允许您更改数据的格式。在任何情况下,您都应该只创建一次VAO,除非您需要将新数据重新绑定到缓冲区。

如果您有多个属性,会发生什么?或者,如果要存储位置、颜色和法线,该怎么办?这在我的经验中特别适用于UV坐标

因为这样,属性的大小将仅为2而不是3。因为你的纹理只有2个坐标(忽略3D纹理的可能性)。如果你是在2D中工作呢。attrib指针允许您为该属性指定输入的大小以及类型。它很有用,因为它允许您更改数据的格式。在任何情况下,您都应该只创建一次VAO,除非您需要将新数据重新绑定到缓冲区

“在我看来,我不应该指定格式

不,您没有指定任何格式,只是获取了一个属性位置

这里的选择很简单,因为德国劳埃德船级社在以下方面为您提供了很大的灵活性:

  • 为您将其他数据类型转换为float
  • 具有不同大小的传递向量
  • 规范化非浮点类型
  • 对属性使用交错、非零偏移缓冲区
  • 这只能“部分”自动完成。当然,您可以内省着色器并确定您的属性确实是一个
    vec3
    ,因此3个浮动,但这仍然不能告诉GL顶点数组缓冲区对象中的数据是什么样子的。值得注意的是,它允许包含

    • 其他兼容类型(请注意,
      glVertexAttribPointer
      /
      glVertexAttribFormat
      可以采用一系列不同的类型,而不仅仅是
      GL\u FLOAT
    • 低维数据(谁告诉德国劳埃德船级社的?)
    • 交错数据(谁告诉德国劳埃德船级社步幅是多少?)
    • 非零偏移的数据(谁告诉德国劳埃德船级社什么是基准偏移?)
    • 可能需要或不需要标准化的数据(谁告诉德国劳埃德船级社?)
    回答“谁告诉你”:你呼叫
    glVertexAttribFormat

    “在我看来,我不应该指定格式

    嗯,不,你没有指定任何形式