OpenGL 4.0++核心配置文件中固定功能管线的属性位置是什么?

4

我想了解没有附加着色器的情况下,nVidia OpenGL驱动程序中固定管道的属性位置:

glVertex = 0
glColor = 3
glNormal = ?
glTexCoord = ?
glMultiTexCoord 0..7 = ?
glSecondaryColor = ?
glFog = ?

我在实践中找到了顶点和主要颜色的位置,但了解所有位置仍然很好。

如果您想知道为什么,那么出于兼容性原因,甚至用于GLSL调试(只是为了查看当着色器尚未正常工作时是否将正确的数据传递给正确的位置)等等...


2
你需要在GLSL中使用gl_Vertexgl_Color等来访问它们。它们没有任何“属性位置”。虽然你不应该再使用它们了。如果你已经在使用着色器,那为什么不像应该做的那样创建自己的属性和uniform呢? - vallentin
你误解了,我在VAO中有一个模型,并希望配置VAO位置以与固定管线(无GLSL)兼容。 - Spektre
1
它们不应该一起工作。 - vallentin
2
他们可能会这样做,但那不是你应该这样做的方式。你应该避免使用任何来自固定功能管道的东西。 - vallentin
1
好的,不要混合新旧代码,要么使用新的,要么使用旧的。它们不应该以任何方式一起工作,你最好只使用新的代码。 - vallentin
显示剩余2条评论
2个回答

14

除了NVIDIA驱动程序,这并不可靠。兼容的驱动程序只会将glVertexPointer(...)别名为属性槽0。NV在许多年前就设计了一种标准的非标准方案,在其中将所有固定功能指针别名映射到某些属性位置,但我不知道新的NV驱动程序是否支持此功能(老实说,我从来没有关心过,这是一个如此糟糕的做法)。您可能仍然可以找到NV的文档,以了解其别名映射,但通过利用其非标准行为,您不会使任何人受益。

虽然其他驱动程序也可能将固定功能指针别名映射到通用顶点属性位置,但不存在有关它们映射的文档。与NV不同,我不会相信映射不会在驱动程序版本、硬件或平台之间发生变化。实际上,即使使用NV驱动程序,您也不应该利用此功能 - 它旨在促进遗留支持,而不是作为用于新软件的功能。

根本原因是使用通用顶点属性,或者使用兼容性配置文件和仍支持专门设计用于获取固定功能顶点数据的预声明变量的GLSL版本(例如gl_Colorgl_Normalgl_MultiTexCoord0...7,...)。但不要像您描述的那样混合使用。

还需要一些时间来查看glGetPointerv(...)。如果您想在GLSL之外获取有关固定功能指针的信息,则应该这样做。不要依赖于顶点属性别名,因为属性位置的概念本质上是可编程管线功能。在OpenGL 2.0之前的未扩展OpenGL中甚至不存在它(它是通过ARB Vertex Program assembly language引入并在GLSL中推广成核心)。


更新:

虽然我仍然强烈反对使用此信息,但我能够找到您想要的确切内容:

NVIDIA OpenGL Shading Language支持版本发布说明 - 2006年11月9日 - 第7-8页

顶点属性别名

GLSL试图消除顶点属性的别名,但这与NVIDIA的硬件方法密不可分,并且对于维护NVIDIA客户所依赖的现有OpenGL应用程序的兼容性是必要的。

NVIDIA的GLSL实现因此不允许内置顶点属性与使用glBindAttribLocation将通用顶点属性指定到特定顶点属性索引的情况发生冲突。例如,您不应同时使用gl_Normal(内置顶点属性)和glBindAttribLocation将名为“whatever”的通用顶点属性绑定到顶点属性索引2,因为gl_Normal会与索引2别名相同。

  表格摘录

如果您想知道,这也在ARB顶点程序扩展规范的表格X.1中概述。我之所以特别提到NV,是因为他们选择在GLSL中重用了别名,而其他厂商的符合实现只会遵守GLSL中的第一个别名(从glVertexPointer (...)0)。


正如我之前所写的,这只是为了我的测试而不是输出/官方代码。无论如何,我正在使用NV用于OpenGL(因为所有其他供应商的糟糕的ogl驱动程序没有使用其他任何东西的意义)。感谢您提供的列表,我接受了您的答案。 - Spektre

7
我将这个答案从重复的已删除问题“使用顶点属性索引0,而不是固定功能属性GL_VERTEX_ARRAY”移动到此处。
如果OpenGL扩展ARB_vertex_program;修改第2.7节,顶点规格说明有效,则固定功能属性和属性索引之间存在映射关系:

Setting generic vertex attribute zero specifies a vertex; the four vertex coordinates are taken from the values of attribute zero. A Vertex2, Vertex3, or Vertex4 command is completely equivalent to the corresponding VertexAttrib command with an index of zero. Setting any other generic vertex attribute updates the current values of the attribute. There are no current values for vertex attribute zero.

Implementations may, but do not necessarily, use the same storage for the current values of generic and certain conventional vertex attributes. When any generic vertex attribute other than zero is specified, the current values for the corresponding conventional attribute in Table X.1 become undefined. Additionally, when a conventional vertex attribute is specified, the current values for the corresponding generic vertex attribute in Table X.1 become undefined. For example, setting the current normal will leave generic vertex attribute 2 undefined, and vice versa.

| Generic Attribute |  Conventional Attribute  | Conventional Attribute Command |
|-------------------|--------------------------|--------------------------------|
| 0                 | vertex position          | Vertex                         |
| 1                 | vertex weights 0-3       | WeightARB, VertexWeightEXT     |
| 2                 | normal                   | Normal                         |
| 3                 | primary color            | Color                          |
| 4                 | secondary color          | SecondaryColorEXT              |
| 5                 | fog coordinate           | FogCoordEXT                    |
| 6                 | -                        | -                              |
| 7                 | -                        | -                              |
| 8                 | texture coordinate set 0 | MultiTexCoord(TEXTURE0, ...    |
| ...               |                          |                                |
这意味着顶点属性0和固定功能属性GL_VERTEX_ARRAY之间存在“映射”,但不一定存在任何其他顶点属性的映射。

根据NVIDIA OpenGL Shading Language Support发布说明;2006年11月9日;-第7-8页,Nvidia更进一步。如上表所示,固定功能属性和顶点属性索引之间存在实际映射关系。
另请参阅OpenGL 4.0++核心配置文件中固定功能管线的属性位置是什么?的答案。
我进行了一些测试,并得出以下结论:下面的代码在Nvidia GeForce 940MX上运行,但无法在集成的Intel(R) HD Graphics 620上运行。
三角形如下所示:
static const float varray[]
{ 
  // x        y         red   green blue  alpha
    -0.707f, -0.75f,    1.0f, 0.0f, 0.0f, 1.0f, 
     0.707f, -0.75f,    1.0f, 1.0f, 0.0f, 1.0f,
     0.0f,    0.75f,    0.0f, 0.0f, 1.0f, 1.0f
};

可以通过glBegin/glEnd序列绘制,无需任何着色器。

glBegin( GL_TRIANGLES );
for ( int j=0; j < 3; ++j )
{
    glVertex2fv( varray + j*6 );
    glColor4fv( varray + j*6 + 2 );
}
glEnd();

通过指定固定函数属性,
glVertexPointer( 2, GL_FLOAT, 6*sizeof(*varray), varray );
glColorPointer( 4, GL_FLOAT, 6*sizeof(*varray), varray+2 );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
glDrawArrays( GL_TRIANGLES, 0, 3 );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );

在Nvidia硬件上,通过指定索引为0和3的通用顶点属性数组来对应固定功能属性GL_VERTEX_ARRAYGL_COLOR_ARRAY

glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 6*sizeof(*varray), varray );
glVertexAttribPointer( 3, 4, GL_FLOAT, GL_FALSE, 6*sizeof(*varray), varray+2 );
glEnableVertexAttribArray( 0 );
glEnableVertexAttribArray( 3 );
glDrawArrays( GL_TRIANGLES, 0, 3 );
glDisableVertexAttribArray( 0 );
glDisableVertexAttribArray( 3 );

同样的代码可以通过使用以下OpenGL 2.0着色器程序来运行。
顶点着色器:
#version 110

varying vec4 vertCol;

void main()
{
    vertCol     = gl_Color;
    gl_Position = gl_Vertex;
}

以下是针对OpenGL 4.0着色器程序的翻译:

下面是OpenGL 4.0着色器程序:

顶点着色器

#version 400

layout (location = 0) in vec3 inPos;
layout (location = 3) in vec4 inColor;

out vec4 vertCol;

void main()
{
    vertCol     = inColor;
    gl_Position = vec4(inPos, 1.0);
}

为了完整起见,在上述两种情况下都可以工作的片段着色器

#version 400

in vec4 vertCol;

out vec4 fragColor;

void main()
{
    fragColor = vertCol;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接