我将浮点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>
答案 0 :(得分:1)
没有计算着色器,唯一想到的就是使用片段着色器来做到这一点。对于100x100纹理,您可以尝试渲染到20x20网格纹理,让片段着色器执行5x5查找(使用GL_NEAREST)来确定最小值和最大值,然后下载20x20纹理并在CPU上执行其余操作。或者做另一次通过再次减少它。我不知道哪种网格尺寸更有效,但是你必须要进行实验。也许this可以帮助,或谷歌搜索&#34;减少gpu&#34;。
答案 1 :(得分:0)
在1x1帧缓冲区和着色器样本整个先前渲染的纹理内渲染1个顶点。那样你在GPU上测试纹理应该足够快到实时(或不是?),但是它肯定比在CPU上做得快,输出将是最小值/最大值。
我还遇到了解决方案,尝试使用mipmap-texture并经历不同的级别。
这些链接可能会有所帮助:
希望这有帮助。