Three.js 着色器扩展的干扰行为
为了符合每个图形硬件配置,我尝试允许我的应用程序处理MRT渲染或单个gl_FragColor渲染。通过检查是否在着色器中定义了GL_EXT_draw_缓冲区,我使用GLSLThree.js 着色器扩展的干扰行为,three.js,glsl,webgl,shader,fragment-shader,Three.js,Glsl,Webgl,Shader,Fragment Shader,为了符合每个图形硬件配置,我尝试允许我的应用程序处理MRT渲染或单个gl_FragColor渲染。通过检查是否在着色器中定义了GL_EXT_draw_缓冲区,我使用GLSL#extension和#ifdef预处理器指令,将相同的着色器用于这两种用途。当一些着色器使用此扩展而其他着色器不使用时,我遇到了一些问题。事实上,即使指令被认为是错误的,也会调用代码。我决定创建一个简单的示例来检查ThreeJS和WebGL中的这个问题 方法: 为了直观地调试是否定义了扩展,我使用以下GLSL片段着色器代码:
#extension
和#ifdef
预处理器指令,将相同的着色器用于这两种用途。当一些着色器使用此扩展而其他着色器不使用时,我遇到了一些问题。事实上,即使指令被认为是错误的,也会调用代码。我决定创建一个简单的示例来检查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会添加该指令
调试:
以下是一些屏幕截图,详细说明了不同的三个.ShaderMaterial
实例化顺序,并带有以下标题:
- 1.1(左上角)具有
,预期为绿色扩展。drawBuffers:true
- 1.2(右上角)具有
,预期为红色扩展。drawBuffers:false
- 2(底部)具有
,预期为红色扩展。drawBuffers:false
- 1.1和1.2共享相同的用户GLSL代码
THREE.ShaderMaterial
共享相同的GLSL用户代码时,我将extension.drawBuffers
启用到第一个,而不是第二个。但是,第二个命令进入#ifdef
指令。我看过ThreeJS,错误似乎来自管理新THREE.WebGLProgram
的方式
实际上,当ThreeJS例程进入WEBGLPrograms.capabilities.acquireProgram
时,它只比较用户着色器代码,而不比较编译的着色器代码。两个三个。具有不同扩展标志的ShaderMaterial
被视为相同。它只考虑已定义的第一个着色器
(2) 此外,当使用新代码创建新着色器时,检查相同的#ifdef
,这似乎取决于以前的着色器扩展。我对这个问题没有任何线索,我试图检查从ThreeJS编译的GLSL代码,但似乎没有任何错误,这可能是一个原生WebGL问题
我认为我需要深入研究这个问题,我不是一个以英语为母语的人。如果不完全清楚,我道歉。如果你需要,我会提供任何信息
提前感谢您为解决此棘手问题做出的贡献:)尝试回答此问题:
- 问题(1):正如建议的那样,您可以使用自定义定义来解决问题。例如,您可以定义一个名为
的新变量,而不是选中draw\u BUFFER
。如果每个可用的扩展都由ThreeJS管理,效果会更好。我将尝试一个关于它的请求GL\u EXT\u draw\u buffers
- 问题(2):如上所述,通过检查,扩展启用了上下文,而未启用着色器。由于预处理器指令是在着色器代码发送到GPU后编译的,因此最好在创建任何着色器程序之前调用
,以避免此类问题glContext.getExtension
这两个问题彼此有很大的关联,但我尝试将它们分开以获得更简单的答案。WebGL中的扩展在每个上下文中启用一次,而不是每个着色器。如果启用扩展,则会为所有着色器启用该扩展。另外,AFAIK three.js只是始终启用所有扩展。这对您有帮助吗<代码>materialDrawBuffer。定义[“绘制缓冲区”]=“”然后
#ifdef DRAW_BUFFER
而不是ifdef GL_EXT_DRAW_buffers
@gman,我接受你的答案。但是你的解释仍然有问题。为什么点2在(3)中是红色的?如果WebGL启用每个上下文的扩展,它应该呈现为绿色。。。今天我将看一看WebGL规范,但它仍然非常奇怪@WestLangley,这个解决方案应该可行,但是您不认为最好通过修改WEBGLPrograms.capabilities.acquireProgram
来改变在3JS中创建新着色器的方式,这样它也会检查启用的扩展吗?已经为ThreeJS做了贡献,所以我认为这对我来说并不难。我认为我的建议是解决你问题的正确方法。启用扩展并不意味着着色器必须使用它。