WebGL 着色器保存多个 32 位值

WebGL shader save multiple 32 bit values

我需要在每个 WebGL 片段着色器调用中保存最多 8 个 32 位值(包括没有 OES_texture_float 或 OES_texture_half_float 扩展可用的情况)。看来我只能通过将其打包成 4x8 位 RGBA gl_FragColor 来存储单个 32 位值。 有没有办法存储 8 个值?

在片段着色器中每次调用绘制多于一个 vec4 数据的唯一方法是使用 WEBGL_draw_buffers,它允许您将多个颜色附件绑定到一个帧缓冲区,然后在一个帧缓冲区中渲染所有这些附件使用

的单个片段着色器调用
gl_FragData[constAttachmentIndex] = result;

如果 WEBGL_draw_buffers 不可用,我能想到的唯一解决方法是

  1. 在多个绘图调用中渲染。

    调用 gl.drawArrays 渲染第一个 vec4,然后再次使用不同的参数或不同的着色器渲染第二个 vec4

  2. 渲染基于 gl_FragCoord,您可以在其中更改每个像素的输出。

    换句话说,第一个像素得到第一个vec4,第二个像素得到第二个vec4,等等。例如

    float mode = mod(gl_Fragcoord.x, 2.);
    gl_FragColor = mix(result1, result2, mode);
    

    这样存储的结果是这样的

    1212121212
    1212121212
    1212121212
    

    合并为一个纹理。要获得更多 vec4,您可以这样做

    float mode = mod(gl_Fragcoord.x, 4.); // 4 vec4s
    if (mode < 0.5) {
      gl_FragColor = result1;
    } else if (mode < 1.5) {
      gl_FragColor = result2;
    } else if (mode < 2.5) {
      gl_FragColor = result3;
    } else {
      gl_FragColor = result4;
    }
    

    这可能比方法 #1 快,也可能不快。您的着色器更复杂,因为它可能会为每个像素同时计算 result1 和 result2,但根据 GPU 和流水线,您可能会免费获得其中的一些。

至于即使没有 OES_texture_float 也能输出 32 位值,您基本上必须使用上述 3 种技术之一写出更多 8 位值。

在 WebGL2 中,绘制缓冲区是一项必需的功能,而在 WebGL1 中它是可选的。在 WebGL2 中,还有将顶点着色器(变量)的输出写入缓冲区的变换反馈。