代码之家  ›  专栏  ›  技术社区  ›  HankMoody

运行时修改WebGL明暗器所需的最小代码是什么?

  •  0
  • HankMoody  · 技术社区  · 6 年前

    假设我已经创建了一个WebGL程序,附加了一些初始的明暗器,链接了该程序,并进行了验证,一段时间后我想修改其中一个附加明暗器的源。

    我应该用 gl.createProgram() 或者我可以重新使用它并附加明暗器?

    我对此有点困惑,因为有几种方法可以调用:

    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    gl.attachShader(program, shader);
    gl.linkProgram(program);
    gl.validateProgram(program);
    

    仅修改程序中的一个明暗器需要以下哪项?我想链接是必需的。是否需要创建新的明暗器实例,或者可以重用该实例并使用 gl.shaderSource() 传递新的源?是否需要将新/旧材质球附加到程序。我应该从程序中分离旧的明暗器吗?

    0 回复  |  直到 6 年前
        1
  •  2
  •   solidpixel    6 年前

    如果您愿意替换现有对象的内容,则无需创建新的明暗器或程序对象。如果要替换现有对象的内容,则最小集为:

    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    // gl.attachShader(program, shader);
    gl.linkProgram(program);
    

    也就是说,您不需要将明暗器对象附加到程序,因为它已经附加,但您需要执行其他所有操作。

    是否需要创建新的明暗器实例,或者可以重用该实例并使用gl.shader source()传入新的源?

    两者都可以。

    是否需要将新/旧材质球附加到程序。

    如果创建一个新的明暗器对象,那么是的,它显然需要附加到程序对象上,或者在程序中不可用。

    我应该从程序中分离旧的明暗器吗?

    是的,你会得到 GL_INVALID_OPERATION 如果已在该着色器类型位置附加了一个明暗器,则尝试附加该明暗器时出错。

    一些一般注意事项:

    • 重新使用的程序对象将继续反映旧的明暗器行为,直到调用 linkProgram .
    • 在新程序中,统一绑定和属性绑定的位置可能会更改,即使它们具有相同的名称。使用静态绑定或在链接后重新查询。
        2
  •  2
  •   gman    6 年前

    不需要创建新的明暗器。你需要打电话 gl.shaderSource 上传新的GLSL,然后 gl.compileShader gl.linkShader .

    不过,这是规范中一个复杂的部分。你想做什么?

    如果链接失败,程序将不再可用。如果链接成功,那么您实际上有了一个新程序,需要查找所有新的属性和统一的位置。

    如果需要,可以创建新的明暗器,并将其附加到现有程序。在附加新的明暗器之前,需要使用 gl.detachShader(prg, oldShader)

    不确定这是否有用,但您可以考虑内部 WebGLProgram 像这样的状态

    class WebGLProgram {
       Shader vertexShader;
       Shader fragmentShader;
    
       // status from last time you called gl.linkProgram
       int linkStatus;
    
       // message from last time you called gl.linkProgram  
       string infoLog;
    
       // internal program created by last SUCCESSFUL linkProgram
       Program validProgram; 
    }
    
    class Program {
      map<string, int> attribLocations;
      map<string, WebGLUniformLocation> uniformLocations;
      GPUProgramCode compiledProgram
    }
    
    class Shader {
      string src;
    
      // status from last time you called gl.compileShader
      int compileStatus;
    
      // message from last time you called gl.compileShader  
      string infoLog;
    
      // internal shader created from last successful compile
      GPUShaderCode compiledShader;
    }
    

    渲染时唯一重要的是 validProgram WebGL程序 有有效的程序。比如说

    const prg = gl.createProgram();
    gl.attachShader(prg, validCompiledVertexShader);
    gl.attachShader(prg, validCompiledFragmentShader);
    gl.linkProgram(prg);   
    
    // our imaginary prg.validProgram now has a valid program
    
    gl.detachShader(prg, validCompiledVertexShader);
    gl.detachShader(prg, validCompiledFragmentShader);
    gl.deleteShader(validCompiledVertexShader);
    gl.deleteShader(validCompiledFragmentShader);
    

    是使用着色器的完全有效的方法。他们只需要停留足够长的时间打电话 linkProgram .