3

我想知道nVidia OpenGL 驱动程序的固定管道(未附加着色器)内的属性位置:

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

根据经验,我找到了顶点和原色位置,但仍然会很高兴了解它们。

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

4

2 回答 2

13

在 NVIDIA 驱动程序之外,这不起作用(可靠)。兼容的驱动程序只会别名glVertexPointer (...)为属性 slot 0。许多年前,NV 在他们无限的智慧中设计了一个标准的非标准方案,他们将所有固定函数指针别名到某些属性位置,但我不知道新的 NV 驱动程序是否支持这一点(老实说,我从来没有足够在意尝试,这是一种不好的做法)。您可能仍然可以找到 NV 的别名映射文档,但利用他们的非标准行为并没有使任何人受益。

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

底线是,改用通用顶点属性或使用兼容性配置文件和仍然支持预先声明的变量的 GLSL 版本,这些变量是专门为获取固定功能顶点数据而设计的(例如gl_Color, gl_Normal, gl_MultiTexCoord0...7, ...)。但不要混合搭配您所描述的两种方式。

也需要一些时间来复习glGetPointerv (...)。如果您想在 GLSL 之外获取有关固定函数指针的信息,这是正确的方法。不要依赖顶点属性别名,因为属性位置的概念本质上是一个可编程的管线特征。它甚至不存在于 2.0 之前的未扩展 OpenGL 中(它由ARB Vertex Program 汇编语言引入,并通过 GLSL 提升为核心)。


更新:

虽然我仍然强烈建议不要使用此信息,但我能够准确找到您想要的信息:

NVIDIA OpenGL 着色语言支持的发行说明- 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)。

于 2013-12-13T19:12:58.413 回答
4

我将这个答案从重复和删除的问题Using vertex attribute index 0, instead of Fixed-Function attribute GL_VERTEX_ARRAY移到了这里。


如果 OpenGL 扩展ARB_vertex_program; Modify Section 2.7, Vertex Specification有效,则固定函数属性和属性索引之间存在映射:

设置通用顶点属性零指定一个顶点;四个顶点坐标取自属性零的值。 Vertex2、Vertex3 或 Vertex4 命令完全等同于索引为零的相应 VertexAttrib 命令。设置任何其他通用顶点属性会更新属性的当前值。顶点属性零没有当前值。

实现可以但不一定对通用和某些常规顶点属性的当前值使用相同的存储。当指定除零以外的任何通用顶点属性时,表 X.1 中相应常规属性的当前值将变为未定义。此外,当指定常规顶点属性时,表 X.1 中相应通用顶点属性的当前值将变为未定义。例如,设置当前法线将使通用顶点属性 2 未定义,反之亦然。

| 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 比NVIDIA OpenGL 着色语言支持发行说明中的​​规定领先一步;2006 年 11 月 9 日;- 第 7-8 页
如上表所示,固定函数属性和顶点属性索引之间存在实际映射。
另请参阅OpenGL 4.0++ 核心配置文件中固定功能管道的属性位置是什么?

我做了一些测试并得出结果,以下 cod 在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 );

并指定索引为 0 和 3 的通用顶点属性数组,其中对应于固定函数属性GL_VERTEX_ARRAYGL_COLOR_ARRAY,对于 Nvidia 硬件:

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 着色器程序:

顶点着色器

#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;
}
于 2018-08-21T13:20:05.050 回答