我将这个答案从重复的已删除问题
“使用顶点属性索引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[]
{
-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_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着色器程序的翻译:
下面是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;
}
gl_Vertex
,gl_Color
等来访问它们。它们没有任何“属性位置”。虽然你不应该再使用它们了。如果你已经在使用着色器,那为什么不像应该做的那样创建自己的属性和uniform呢? - vallentin