假设我已经创建了一个WebGL程序,附加了一些初始着色器,链接了程序,验证了一段时间后我想要修改其中一个附加着色器的源代码。
我应该用gl.createProgram()
创建一个新的WebGL程序,还是我可以重用它并附加着色器?
我对此有点困惑,因为有几种方法可以调用:
gl.shaderSource(shader, source);
gl.compileShader(shader);
gl.attachShader(program, shader);
gl.linkProgram(program);
gl.validateProgram(program);
只修改程序中的一个着色器需要以下哪些?我认为需要链接。我是否需要创建新的着色器实例,或者我可以重用该实例并使用gl.shaderSource()
传递新的源代码?我是否需要将新/旧着色器附加到程序中。我应该从程序中分离旧的着色器吗?
如果您乐意替换现有对象的内容,则无需创建新的着色器或程序对象。如果要替换现有对象的内容,则最小集合为:
gl.shaderSource(shader, source);
gl.compileShader(shader);
// gl.attachShader(program, shader);
gl.linkProgram(program);
即,您不需要将着色器对象附加到程序,因为它已经附加,但您需要执行其他所有操作。
我是否需要创建新的着色器实例,或者我可以重用该实例并使用gl.shaderSource()传入新的源代码?
要么工作。
我是否需要将新/旧着色器附加到程序中。
如果你创建一个新的着色器对象然后是,它显然需要附加到程序对象,否则它将无法在程序中使用。
我应该从程序中分离旧的着色器吗?
是;如果您尝试附加着色器(如果已在该着色器类型位置附加了一个着色器),则会出现GL_INVALID_OPERATION
错误。
一些一般性说明:
linkProgram
之前,重用的程序对象将继续反映旧的着色器行为。您无需创建新着色器。你需要调用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
上的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
。