如何编码和发送浮点数据到GLSL从Javascript/THREE.js和解码结果

How to encode and send float data to GLSL from Javascript/THREE.js and decode results

本文关键字:Javascript GLSL 结果 解码 js THREE 数据 何编码 编码      更新时间:2023-09-26

我想编码对象位置(x,y,z)并发送到GLSL着色器,解码数据,执行一些计算并将结果发送回CPU。我已经研究了这个问题,并找到了部分答案,如解码rgb值为glsl中没有位移位的单浮点数,但我在编码和解码结果方面没有成功。

这是我的一部分代码。

function init() {
  ...
  buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([
      -1.0, 1.0,
      -1.0, -1.0,
      1.0, -1.0,
      1.0, 1.0
    ]),
    gl.STATIC_DRAW
  );
  texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  vec1 = new THREE.Vector3(2.6, 3.3, 100.80); //example position vector
  data = new Uint8Array([float2Color(vec1.x).r, float2Color(vec1.x).g, float2Color(vec1.x).b, 255, //x
    float2Color(vec1.y).r, float2Color(vec1.y).g, float2Color(vec1.y).b, 255, //y
    float2Color(vec1.z).r, float2Color(vec1.z).g, float2Color(vec1.z).b, 255 //z
  ]);
   // This encodes to give me int8Array [ 2, 0, 0, 255, 3, 0, 0, 255, 100, 0, 2 more… ]
  
  gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
}
//render function
function render() {
  ...
  gl.drawArrays(gl.POINTS, 0, 2);
  var pixels = new Uint8Array(WIDTH * HEIGHT * 4);
  gl.readPixels(0, 0, WIDTH, HEIGHT, gl.RGBA, gl.FLOAT, pixels);
  pixels = new Uint8Array(pixels.buffer);
  
  //After getting the results from GLSL, pixels now look like this
  //Uint8Array [ 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, … ]
 
  var color = {
    r: pixels[0],
    g: pixels[1],
    b: pixels[2]
  };
  float1 = decodeVec3ToFloat(color); // I would like to decode and use the data after the position is updated in GLSL
}
function float2Color( f ) {
        b = Math.floor(f / 255.0 / 255.0);
        g = Math.floor((f - (b * 255.0 * 255.0) ) / 255.0);
        // r = Math.floor(f - (b * 255.0 * 255.0) - (g * 255.0) );
        r = Math.floor(f % 255);
        return {r:r, g:g, b:b};
    }
function decodeVec3ToFloat(color) {
        var result;
        result = color.r * 255.0;
        result += color.g * 255.0 * 255.0;
        result += color.b * 255.0 * 255.0 * 255.0;
        return result;
    }

我自己也一直在处理这类事情。你可以使用DataTextures来实现这一点,并通过模拟着色器将它们作为缓冲区传入和传出。到目前为止,我发现的最好的例子使用了一个过时的版本Three.js (v58),但可以很容易地更新。我发现更新脚本很有帮助,然后摆弄它,直到我完全理解了我的用例。请注意,在这个例子中,甚至有固定的值在模拟着色器中传递,以及在缓冲区中渲染的x,y,z值的变化。好运!

更新:

我已经发现,旧的三个。我在上面使用的FBOUtils脚本已经更新和重新制作,现在被称为THREE。gpu计算渲染器——工作很棒!(v80)