颜色属性和使用 gl_Color 的区别

The difference between a color attribute and using gl_Color

大多数 GLSL 着色器都在顶点着色器中使用颜色属性,该属性将作为变化转发给片段着色器。像这样:

attribute vec4 position;
attribute vec4 color;
uniform mat4 mvp;
varying vec4 destinationColor;

void main(){
  destinationColor = color;
  gl_Position = mvp * position;
};

可以通过 glVertexAtribPointer() 为每个顶点传递一种颜色或通过 glVertexAttrib4fv() 为所有顶点传递一种全局颜色来设置颜色。我试图了解顶点着色器中预定义变量 gl_Color 的区别(如果有任何区别的话)。即

attribute vec4 position;
uniform mat4 mvp;
varying vec4 destinationColor;

void main(){
  destinationColor = gl_Color;
  gl_Position = mvp * position;
};

并使用 glColorPointer() 为每个顶点传递一种颜色或 glColor4fv() 为所有顶点使用全局颜色。对我来说,第二个着色器看起来更好(=更有效率?),因为它使用更少的属性。但是所有教程和在线资源都使用第一种方法 - 所以我想知道我是否遗漏了什么或者是否没有任何区别。 编写 GLSL 着色器时有什么更好的做法?

如果我没记错的话 gl_Color 是旧样式 API 的弃用残余,没有 VAO/VBO 使用 glBegin() ... glEnd()。如果您转到核心配置文件,则不再有 gl_Color ...所以我假设您使用旧的 OpenGL 版本或兼容性配置文件。

如果您尝试在核心配置文件(例如 4.00)中使用 gl_Color,您会得到:

0(35) : error C7616: global variable gl_Color is removed after version 140

这意味着 gl_Color 已从 GLSL 1.4

中删除

这不完全是性能问题,而是图形渲染 SW 体系结构或 GL 调用层次结构的变化(如果需要)。

To me the second shader looks better (= more efficient?), because it uses less attributes.

它并没有使用更少的属性。它只是使用较少的显式属性声明。为 OpenGL 获取该颜色值所需的所有工作仍然存在。它仍在进行中。硬件仍在从缓冲区对象中获取数据或从 glColor 上下文值或其他任何内容中获取数据。

您只是在着色器的文本中看不到它。但仅仅因为你没有看到它并不意味着它是免费发生的。

首选用户定义的属性,原因如下:

  • 用户定义的属性可以清楚地表明您的着色器正在使用多少资源。如果您想知道需要为着色器提供多少属性,只需查看全局声明即可。但是对于预定义的属性,您不能这样做;您必须扫描整个顶点着色器以查找任何命名预定义属性的 gl_* 名称。
  • 用户自定义属性可以做更多的事情。如果您想将整数值作为整数传递给顶点着色器,您必须使用用户定义的属性。如果您需要将双精度浮点数传递给顶点着色器,同样,预定义的属性也无济于事。
  • 预定义属性已从核心 OpenGL 上下文中删除。 OSX,例如,不允许兼容性配置文件。您仍然可以使用 OpenGL 2.1,但如果您想在 OSX 上使用任何 OpenGL 3.2 或更高版本,您 不能 使用已删除的功能。并且在 OpenGL 3.1 中删除了内置的顶点属性。
  • 预定义属性从未成为 OpenGL ES 2.0+ 的一部分。因此,如果您想编写可以在 OpenGL ES 中工作的着色器,您又 不能 使用它们。

所以基本上,现在没有理由使用它们。