在运行时修改WebGL着色器所需的最低代码是什么?

问题描述 投票:1回答:2

假设我已经创建了一个WebGL程序,附加了一些初始着色器,链接了程序,验证了一段时间后我想要修改其中一个附加着色器的源代码。

我应该用gl.createProgram()创建一个新的WebGL程序,还是我可以重用它并附加着色器?

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

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

只修改程序中的一个着色器需要以下哪些?我认为需要链接。我是否需要创建新的着色器实例,或者我可以重用该实例并使用gl.shaderSource()传递新的源代码?我是否需要将新/旧着色器附加到程序中。我应该从程序中分离旧的着色器吗?

javascript opengl-es webgl shader
2个回答
2
投票

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

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

即,您不需要将着色器对象附加到程序,因为它已经附加,但您需要执行其他所有操作。

我是否需要创建新的着色器实例,或者我可以重用该实例并使用gl.shaderSource()传入新的源代码?

要么工作。

我是否需要将新/旧着色器附加到程序中。

如果你创建一个新的着色器对象然后是,它显然需要附加到程序对象,否则它将无法在程序中使用。

我应该从程序中分离旧的着色器吗?

是;如果您尝试附加着色器(如果已在该着色器类型位置附加了一个着色器),则会出现GL_INVALID_OPERATION错误。

一些一般性说明:

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

2
投票

您无需创建新着色器。你需要调用gl.shaderSource上传新的GLSL,然后上传gl.compileShadergl.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上的WebGLProgram有一个有效的程序。所以举个例子

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

© www.soinside.com 2019 - 2024. All rights reserved.