我正在开发一个游戏引擎并处理延迟渲染管道。完成(第二遍)(着色)着色器后,我开始在我拥有的其他各种计算机上测试管道。有趣的是,在我的旧笔记本电脑上,我在每个4x8像素组上得到了这种奇怪的伪像(下面的示例)。它看起来像着色器正在执行并最终返回正确的颜色,但是以非常随机的方式。
此问题不是错误报告或解决方案请求。我用下面的代码修补程序解决了这个问题。这个主题是为了更好地理解为什么会发生这种情况,并为可能受同一问题影响的任何其他人提供见解。
更详细地描述效果: 大约50%的屏幕具有4x8像素组,这些像素高度调整实际产生的颜色。 这些4x8组在屏幕上的每个帧上随机放置,产生“静态”效果。 某些型号着色不同。如下所示,反光兔子呈蓝色,但折射球呈黄色。这似乎不是Gbuffer问题,因为它们都是从我确定正确的相同纹理中采样(因为我可以在屏幕上同时看到它)。 不同对象的4x8块具有更高的显示正确颜色的速率。你可以看到折射兔子大多是正确的,但反光地板和折射球只是白色和黄色。 根据GPU上运行的其他程序,4x8块的色调会发生巨大变化。
破碎着色器的伪代码就像
out vec3 FragColor; // Out pixel of fragment shader
void main() {
for (int i=0; i<NumberOfPointLights; i++) {
... Lighting calculation code...
FragColor += lighting;
}
for (int i=0; i<NumberOfSpotLights; i++) {
... Lighting calculation code...
FragColor += lighting;
}
for (int i=0; i<NumberOfDirectionalLights; i++) {
... Lighting calculation code...
FragColor += lighting;
}
}
为了解决这个问题,我简单地初始化了一个临时变量来保存输出颜色,在光照计算过程中写入,然后将其写入最后的片段输出。如下:
out vec3 FragColor; // Out pixel of fragment shader
void main() {
vec3 outcolor = vec3(0);
for (int i=0; i<NumberOfPointLights; i++) {
... Lighting calculation code...
outcolor += lighting;
}
for (int i=0; i<NumberOfSpotLights; i++) {
... Lighting calculation code...
outcolor += lighting;
}
for (int i=0; i<NumberOfDirectionalLights; i++) {
... Lighting calculation code...
outcolor += lighting;
}
FragColor = outcolor;
}
我很惊讶这是有效的,因为我认为默认情况下会假设此行为。对片段输出的写入实际上并不是每次都写入VRAM,而是在最后。我的印象是在着色器执行后读取片段输出变量,因此它的全局性。
我的旧笔记本电脑使用带有Optimus技术的GT540m和集成的Intel 3000显卡(这里没有使用)
我的新台式电脑使用的是GTX1070。在运行应用程序期间,两个GPU都使用非常少的VRAM,小于100MB。 Shader正在使用#version 400 core
编译
这是一个驱动程序错误。这里没什么可看的了。
可以读取和写入输出变量。这是GLSL的一部分。因此,似乎司机只是搞砸了它的实施。