为了符合每个图形硬件配置,我试图让我的应用程序处理 MRT 渲染或单个 gl_FragColor 渲染。我通过使用 GLSL #extension
和#ifdef
预处理程序指令,通过检查着色器中是否定义了 GL_EXT_draw_buffers ,对两种用法使用相同的着色器。当一些着色器使用此扩展而其他不使用时,我遇到了一些麻烦。实际上,即使指令被认为是假的,代码也被调用了。我决定创建一个简单的示例来检查 ThreeJS 和 WebGL 中的这个问题。
方法:
为了可视化调试是否定义了扩展名,我使用以下 GLSL 片段着色器代码:
uniform vec3 diffuse;
uniform float opacity;
void main() {
#ifdef GL_EXT_draw_buffers
gl_FragColor = vec4( 0.0, 1.0, 0.0, 1.0 );
#else
gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
#endif
}
将着色器发送到 GPU 时,指令由 ThreeJS 添加。
调试:
以下是一些截图,详细介绍了不同的THREE.ShaderMaterial
实例化顺序以及以下字幕:
extensions.drawBuffers : true
,预计绿色 extensions.drawBuffers : false
,预计红色 extensions.drawBuffers : false
,预计红色 此处的代码示例:Draw Buffer Define Strange Behavior
检测问题:
(1)当创建两个不同的THREE.ShaderMaterial
共享相同的 GLSL 用户代码时,我启用extension.drawBuffers
到第一个而不是第二个。但是,第二个进入#ifdef
指令。我查看了 ThreeJS ,错误似乎来自管理新THREE.WebGLProgram
的方式。
实际上,当 ThreeJS 例程进入WEBGLPrograms.capabilities.acquireProgram
时,它只会比较用户着色器代码而不是已编译的着色器代码。具有不同扩展标志的两个THREE.ShaderMaterial
被认为是相同的。它只考虑已定义的第一个着色器。
(2)此外,在使用新代码检查相同#ifdef
创建新着色器时,它似乎依赖于先前的着色器扩展。我对此问题一无所知,我试图检查来自 ThreeJS 的已编译 GLSL 代码,似乎没有任何错误,这可能是本机 WebGL 问题
我认为我需要深入研究这个问题,而且我不是母语人士。如果不完全清楚,我道歉。如果您需要,我会提供任何信息。
提前感谢您为解决这个棘手的问题做出贡献:)
答案 0 :(得分:0)
试图回答这个问题:
问题(1):建议@WestLangley,您可以使用自定义定义来解决问题。您可以定义一个名为GL_EXT_draw_buffers
的新变量,而不是检查DRAW_BUFFER
。如果由ThreeJS管理每个可用的扩展,可能会更好。我将尝试拉取请求。
问题(2):正如@gman所述,并且通过检查WebGL specifications,扩展是启用上下文而不启用着色器。因为一旦将着色器代码发送到GPU就会编译预处理器指令,所以最好在创建任何着色器程序之前调用glContext.getExtension
以避免此类问题。
这两个问题彼此密切相关,但我试图将它们拆分以获得更简单的答案。