0

我将浮点 gpgpu 值存储在 webgl RGBA 渲染纹理中,仅使用 r 通道来存储我的数据(我知道我应该使用更有效的纹理格式,但这是一个单独的问题)。

是否有任何有效的方法/技巧/破解来查找全局最小和最大浮点值而不诉诸 gl.readPixels?请注意,仅导出浮点数据在 webgl 中很麻烦,因为 readPixels 尚不支持读取 gl.FLOAT 值。

这是我目前做事的要点:

if (!gl) {
    gl = renderer.getContext();
    fb = gl.createFramebuffer();
    pixels = new Uint8Array(SIZE * SIZE * 4);
}

if (!!gl) {
    // TODO: there has to be a more efficient way of doing this than via readPixels...
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, data.rtTemp2.__webglTexture, 0);

    if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
        // HACK: we're pickling a single float value in every 4 bytes 
        // because webgl currently doesn't support reading gl.FLOAT 
        // textures.
        gl.readPixels(0, 0, SIZE, SIZE, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

        var max = -100, min = 100;

        for (var i = 0; i < SIZE; ++i) {
            for (var j = 0; j < SIZE; ++j) {
                var o = 4 * (i * SIZE + j);
                var x = pixels[o + 0];
                var y = pixels[o + 1] / 255.0;
                var z = pixels[o + 2] / 255.0;

                var v = (x <= 1 ? -1.0 : 1.0) * y;
                if (z > 0.0) { v /= z; }

                max = Math.max(max, v);
                min = Math.min(min, v);
            }
        }

        // ...
    }
}

(使用片段着色器以适合 UNSIGNED_BYTE 解析的以下格式输出浮点数据......

<script id="fragmentShaderCompX" type="x-shader/x-fragment">
uniform sampler2D source1;
uniform sampler2D source2;

uniform vec2 resolution;

void main() {
    vec2 uv = gl_FragCoord.xy / resolution.xy;

    float v = texture2D(source1, uv).r + texture2D(source2, uv).r;
    vec4 oo = vec4(1.0, abs(v), 1.0, 1.0);

    if (v < 0.0) {
        oo.x = 0.0;
    }

    v = abs(v);
    if (v > 1.0) {
        oo.y = 1.0;
        oo.z = 1.0 / v;
    }

    gl_FragColor = oo;
}
</script>
4

2 回答 2

1

如果没有计算着色器,唯一想到的就是使用片段着色器来做到这一点。对于 100x100 纹理,您可以尝试渲染到 20x20 网格纹理,让片段着色器执行 5x5 查找(使用 GL_NEAREST)以确定最小值和最大值,然后下载 20x20 纹理并在 CPU 上完成其余工作。或者做另一遍以再次减少它。我不知道哪种网格尺寸更有效,但您必须进行试验。也许会有所帮助,或者在谷歌上搜索“reduction gpu”。

于 2013-07-01T17:52:03.443 回答
0

在 1x1 帧缓冲区和着色器样本中渲染 1 个顶点,整个先前渲染的纹理。这样,您在 GPU 上测试纹理应该足够快以进行实时(或不是?),但是它肯定比在 CPU 上测试要快,并且输出将是最小值/最大值。

我还遇到了解决方案来尝试 mipmap-ing 纹理并通过不同的级别。

这些链接可能会有所帮助:

希望这可以帮助。

于 2013-07-01T17:49:09.943 回答