在哪个着色器计算中执行有什么区别吗?

Does it make any difference which shader calculations are performed in?

使用 GLSL,我会执行光照计算、纹理和各种操作;但是在哪个着色器中完成有什么不同吗? 例如,在顶点着色器而不是片段着色器中执行光照计算是否有性能优势?我只需要将最终结果传递给片段着色器并将其添加到片段颜色中。反过来也可以吗?

我的下一个问题是,关于顶点属性和制服:

顶点属性对任何着色器程序中的所有着色器都是全局的吗?例如,假设我们有:

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertices), (GLvoid*)0);

如果我在顶点着色器中声明:

layout (location = 0) in vec3 VertexPosition; 

我也可以在片段着色器中做同样的事情吗?我也可以在属于第二个着色器程序的顶点着色器中做同样的事情吗?

关于制服,我是否可以在该着色器程序的所有着色器中使用制服,只要我声明它们?

uniform mat4 modelMatrix; // In the vertex shader

uniform mat4 modelMatrix; // In the fragment shader

我的最后一个问题是,所有顶点属性是否应该在整个主程序中保持一致?例如,如果我将顶点属性 0 分配为 VertexPosition,那么我就不能再分配那个属性到其他东西,例如 VertexNormal,对吗?这只会发生,除非我禁用顶点属性数组:

glDisableVertexAttribArray(0);

I'd be performing lighting calculations, texturing and all sorts; but does it make any difference which shader it is done in?

想想 OpenGL 管道中的数据流。

大多数图元由 1 个(点)、2 个(线)或 3 个(三角形)顶点组成,但可能会生成数千个片段。因此,由于顶点着色器的运行频率要低得多,因此您可以按顶点计算的任何东西都比按片段便宜。

通常您尽量不要计算每个顶点的整个光照方程 (gouraud),因为它看起来很糟糕,除非您使用过多的顶点。但是,您可以在顶点着色器中将所有光照矢量转换为相同的坐标 space,以简化片段着色器并提高性能。

Are vertex attributes global to all shaders in any shader program?

顶点属性分配给通用位置,这些位置是全局的。但是片段着色器对每个片段进行操作并且没有顶点的概念(再次回想一下数据流)。

Is it possible for me to use uniforms in all the shaders of that shader program so long as I declare them?

另一方面,制服在所有着色器阶段共享。只要名称和类型一致,您就可以在顶点、几何、曲面细分或片段着色器中使用它们。

Should all vertex attributes be consistent throughout the main program?

这个真的没关系,可编程流水线是可编程的。只要 you 知道顶点属性 N 表示什么时候执行着色器,就可以开始了。但是,如果您建立了标准约定,则可以在不更改顶点属性指针的情况下即时交换着色器程序。

在固定功能管道的时代,有一个 standardized convention 顶点位置别名为 0,颜色别名为 3,通常别名为 2 等等。但这纯粹是历史性的,如果您愿意,可以遵循该惯例或创建自己的惯例。