Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Three.js 着色器扩展的干扰行为_Three.js_Glsl_Webgl_Shader_Fragment Shader - Fatal编程技术网

Three.js 着色器扩展的干扰行为

Three.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片段着色器代码:

为了符合每个图形硬件配置,我尝试允许我的应用程序处理MRT渲染或单个gl_FragColor渲染。通过检查是否在着色器中定义了GL_EXT_draw_缓冲区,我使用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代码
(1) (2)(3)(4)

  • 举例说明1.1、1.2、2:1.2和2是错误的
  • 实例化1.2、1.1、2:1.1是错误的
  • 实例化2,然后是1.1,然后是1.2:1.2是错误的
  • 实例化2,然后是1.2,然后是1.1:1.1是错误的
  • 此处的代码示例:

    检测问题:

    (1) 当创建两个不同的
    THREE.ShaderMaterial
    共享相同的GLSL用户代码时,我将
    extension.drawBuffers
    启用到第一个,而不是第二个。但是,第二个命令进入
    #ifdef
    指令。我看过ThreeJS,错误似乎来自管理新
    THREE.WebGLProgram
    的方式

    实际上,当ThreeJS例程进入
    WEBGLPrograms.capabilities.acquireProgram
    时,它只比较用户着色器代码,而不比较编译的着色器代码。两个
    三个。具有不同扩展标志的ShaderMaterial
    被视为相同。它只考虑已定义的第一个着色器

    (2) 此外,当使用新代码创建新着色器时,检查相同的
    #ifdef
    ,这似乎取决于以前的着色器扩展。我对这个问题没有任何线索,我试图检查从ThreeJS编译的GLSL代码,但似乎没有任何错误,这可能是一个原生WebGL问题

    我认为我需要深入研究这个问题,我不是一个以英语为母语的人。如果不完全清楚,我道歉。如果你需要,我会提供任何信息


    提前感谢您为解决此棘手问题做出的贡献:)

    尝试回答此问题:

    • 问题(1):正如建议的那样,您可以使用自定义定义来解决问题。例如,您可以定义一个名为
      draw\u BUFFER
      的新变量,而不是选中
      GL\u EXT\u draw\u buffers
      。如果每个可用的扩展都由ThreeJS管理,效果会更好。我将尝试一个关于它的请求

    • 问题(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做了贡献,所以我认为这对我来说并不难。我认为我的建议是解决你问题的正确方法。启用扩展并不意味着着色器必须使用它。