为什么简单着色器比标准管线慢?

Why is a simple shader slower than the standard pipeline?

我想编写一个非常简单的着色器,它相当于(或比标准管道更快)。然而,即使是最简单的着色器也是可能的:

顶点着色器

void main(void)
{
  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = ftransform();
}

片段着色器

uniform sampler2D Texture0;

void main(void)
{
  gl_FragColor = texture2D(Texture0, gl_TexCoord[0].xy);
}

与标准着色器相比,我的游戏帧率降低了一半,如果显示一些透明图像,性能会很糟糕。我不明白这一点,因为标准着色器 (glUseProgram(0)) 执行照明和 alpha 混合,而此着色器仅绘制平面纹理。是什么让它这么慢?

我想你可能会透支。

我不知道您在什么引擎上使用着色器,但如果您启用了 alpha 混合,那么您最终可能会透支分配。

这样想:

如果您有一个 800x600 的屏幕,并且整个屏幕上有一个二维四边形,那么该二维四边形将调用 480000 次片段着色器,尽管它只有 4 个顶点。

现在,更进一步,让我们假设您有 10 个这样的四边形,一个叠在另一个上面。如果您不从前到后对几何体进行排序,或者如果您使用的是没有深度测试的 alpha 混合,那么您最终将得到 10x800x600 = 4800000 个片段调用。

由于透支,2D 在 OpenGL 上通常非常昂贵。 3D 拒绝许多片段。尽管着色器更复杂,但与 2D 对象相比,3D 对象的调用次数大大减少。

看起来自定义着色器的大幅减速是旧英特尔图形芯片的问题,它似乎模拟了 CPU 上的着色器。

我在最近的硬件上测试了相同的程序,在激活自定义着色器的情况下,丢帧率只有大约 2-3 个百分点。

编辑:错误的理论。请参阅下面的新答案

经过长时间的调查,简单着色器的速度变慢是由于着色器太简单造成的。

在我的例子中,减速是由大量使用 "glBitmap" 的文本渲染引擎引起的,启用纹理会非常慢(无论出于何种原因我无法理解;这些字母很小).

但是,这不会影响标准管道,因为它会承认功能 glDisable(GL_LIGHTING)glDisable(GL_TEXTURE_2D ),它避免了减速,而简单的着色器未能做到这一点,因此甚至会像标准管道一样做更多的工作。将这两个特性引入自定义着色器后,它与标准管线一样快,而且可以添加随机效果而不会对性能产生任何影响!