我正在尝试使用多个渲染目标来保存渲染中的一些其他数据(法线等)。我已经设置了帧缓冲区,就像对这个问题WebGL 2.0: Multiple output textures from the same program的回答一样。当我使用向每个目标写入恒定颜色的虚拟着色器,并使用另一个着色器渲染结果时,一切似乎都可以正常工作。但是,随着着色器复杂性的增加,我遇到了一个问题。我有一个这样的着色器
#version 300 es
precision highp float;
layout(location = 0) out vec4 result_image;
layout(location = 1) out vec4 result_albedo;
layout(location = 2) out vec4 result_normals;
void main(){
result_image = do_some_work(...); // I omitted related functions, textures, uniforms, ...
result_albedo = vec4(0.0, 1.0, 0.0, 1.0);
result_normals = vec4(0.0, 0.0, 1.0, 1.0);
}
此着色器需要花费一些时间进行编译(gl.getError
将其阻塞一段时间后调用gl.linkProgram
)。当我只写第一个纹理时使用它-在gl.bindFramebuffer
之后,我打电话
gl.drawBuffers([
gl.COLOR_ATTACHMENT0,
]);
一切正常。但是当我尝试渲染到多个纹理
gl.drawBuffers([
gl.COLOR_ATTACHMENT0,
gl.COLOR_ATTACHMENT1,
gl.COLOR_ATTACHMENT2,
]);
使用该着色器的第一次绘制使WebGL停顿了几秒钟,随后的所有绘制均正常运行。随着着色器复杂度(在这种情况下为do_some_work(...)
)的增加,此停顿变得更长,并且有时会使WebGL崩溃(由于命令花费的时间太长)。
(注意:当第一次使用1个绘制缓冲区进行渲染,并且切换到3后,在调用drawArrays
浏览器后冻结几秒钟,然后继续正常运行时,也会发生这种情况。
使用MRT而不是没有MRT的第一帧会发生这种失速吗?帧缓冲已经绑定了所有纹理,并且所有纹理都已经通过虚拟着色器写入,因此不是初始化纹理的情况。
是否可以先与多个绘制缓冲区一起使用,使着色器重新编译?请注意,我只会向其他渲染目标输出恒定的颜色,因此这可能不会增加太多的编译时间(如果是这种情况,则linkProgram之后的编译会花费更长的时间。而且如果重新编译,Chrome的着色器缓存将无法工作不使用MRT还是这种情况?)。