我想知道 nVidia OpenGL驱动程序中固定管道(没有添加着色器)内的属性位置:
glVertex = 0
glColor = 3
glNormal = ?
glTexCoord = ?
glMultiTexCoord 0..7 = ?
glSecondaryColor = ?
glFog = ?
根据经验,我找到了顶点和主要颜色位置,但仍然很高兴知道它们。
如果你想知道原因,那么出于兼容性原因,甚至是 GLSL 调试(只是为了看看当着色器还没有工作时我是否将正确的数据传递到正确的位置)等等。
答案 0 :(得分:12)
在NVIDIA驱动程序之外,这不起作用(可靠)。合规驱动程序仅将glVertexPointer (...)
别名为属性插槽 0 。多年前,NV以其无限的智慧设计了一个标准的非标准方案,他们将所有固定功能指针别名化到某些属性位置,但我不知道新的NV驱动程序是否支持这一点(老实说,我从未关心过这个问题) ,这是一个不好的做法)。您可能仍然可以找到NV的别名映射文档,但是您不会利用其非标准行为从中受益。
虽然其他驱动程序也可能将固定函数指针别名为通用顶点属性位置,但其映射不存在任何文档。与NV不同,我不相信映射不会在驱动程序版本,硬件或平台之间发生变化。事实上,即使使用NV驱动程序,也不应该利用这一点 - 它旨在促进传统支持,而不是用作新软件的功能。
底线是,使用通用顶点属性代替或使用兼容性配置文件和仍支持预先声明的变量的GLSL版本,这些变量专门用于获取固定功能顶点数据(例如gl_Color
, gl_Normal
,gl_MultiTexCoord0...7
,...)。但是不要以你描述的方式混合搭配。
还需要一些时间来审核glGetPointerv (...)
。如果你想获得有关GLSL之外的固定函数指针的信息,这是正确的方法。不要依赖顶点属性别名,因为属性位置的概念基本上是可编程管道功能。它甚至不存在于2.0之前的未扩展OpenGL中(它随ARB Vertex Program assembly language一起引入并通过GLSL升级为核心)。
<小时/>
虽然我仍然坚决反对使用这些信息,但我能够找到你想要的东西:
顶点属性别名
GLSL尝试消除顶点属性的混叠,但这是NVIDIA硬件方法不可或缺的一部分,也是维持与NVIDIA客户所依赖的现有OpenGL应用程序兼容的必要条件。
因此,NVIDIA的GLSL实现不允许内置顶点属性与通过 glBindAttribLocation 分配给特定顶点属性索引的通用顶点属性发生冲突。例如,您不应该使用 gl_Normal (内置顶点属性)并使用 glBindAttribLocation 将名为“whatever”的通用顶点属性绑定到顶点属性索引 2 ,因为 gl_Normal 别名为索引 2 。
如果您想知道,ARB Vertex Program extension specification的表X.1中也列出了这一点。我特别提到NV的唯一原因是因为他们选择在GLSL中重复使用别名,而其他供应商的合规实现只会尊重GLSL中的第一个别名(glVertexPointer (...)
到 0 )。
答案 1 :(得分:2)
我将此答案从重复并删除的问题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按照Release Notes for NVIDIA OpenGL Shading Language Support; November 9, 2006; - pp. 7-8中的规定前进。
如上表所示,固定函数属性和顶点属性索引之间存在实际映射。
另请参见What are the Attribute locations for fixed function pipeline in OpenGL 4.0++ core profile?
我做了一些测试,得出的结果是,以下鳕鱼在 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的通用顶点属性数组,它们与Nvidia硬件的固定函数属性GL_VERTEX_ARRAY
和GL_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着色器程序:
顶点着色器
#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;
}