我正在开发游戏引擎并处理延迟渲染管道。完成(第二遍)(着色)着色器后,我开始在我拥有的其他各种计算机上测试管道。有趣的是,在我的旧笔记本电脑上,我在每个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。
正在使用#version 400 core
答案 0 :(得分:1)
这是一个驱动程序错误。这里没有其他内容了。
可以读取和写入输出变量。这是GLSL的一部分。所以看起来驱动程序只是搞砸了它的实现。