如何在JavaScript中读取WebGL GL.bufferData

7

我想在JavaScript中读取存储在GL.bufferData数组中的数据。

这是我的代码:

var TRIANGLE_VERTEX = geometryNode["triangle_buffer"];
GL.bindBuffer(GL.ARRAY_BUFFER, TRIANGLE_VERTEX);
GL.bufferData(GL.ARRAY_BUFFER,new Float32Array(vertices),GL.STATIC_DRAW);`

在WebGL中,是否可以从GPU读取缓冲区数据?如果可能的话,请通过示例代码向我解释。
如何在WebGL中运行时了解GPU的内存大小(已填充和空闲),以及如何调试GPU中的着色器代码和数据。
1个回答

10

在WebGL1中直接读取数据是不可能的。(有关WebGL2,请参见下文)。这是基于OpenGL ES 2.0的WebGL的限制。

有一些解决方法:

  1. 您可以尝试将数据渲染到纹理上,然后使用readPixels读取数据。

    您必须在着色器中将数据编码为字节,因为WebGL中的readPixels只能读取字节。

  2. 您可以包装您的WebGL以存储数据,类似于

    var buffers = {};
    var nextId = 1;
    var targets = {};
    
    function copyBuffer(buffer) {
       // make a Uint8 view of buffer in case it's not already
       var view = new Uint8Buffer(buffer.buffer); 
       // now copy it
       return new UintBuffer(view);
    }
    
    gl.bindBuffer = function(oldBindBufferFn) {
      return function(target, buffer) {
        targets[target] = new Uint8Buffer(buffer.buffer);
        oldBindBufferFn(target, buffer);
      };
    }(gl.bindBuffer.bind(gl));
    
    gl.bufferData = function(oldBufferDataFn) {
       return function(target, data, hint) {
         var buffer = targets[target];
         if (!buffer.id) {
           buffer.id = nextId++;
         }
         buffers[buffer.id] = copyBuffer(data);
         oldBufferDataFn(target, data, hint);
       };
    }(gl.bufferData.bind(gl)));
    

    现在您可以使用以下方法获取数据:

    data = buffers[someBuffer.id];
    

    这可能是WebGL Inspector的功能。

    请注意,上面的代码存在一些问题。其中一个问题是它没有检查错误。检查错误会使它变得更慢,但如果您的代码生成错误,则不检查错误将给您带来不正确的结果。以下是一个简单的例子:

    gl.bufferData(someBuffer, someData, 123456);
    

    这将生成一个INVALID_ENUM错误,并且不会更新someBuffer中的数据,但是我们的代码没有检查错误,所以它已经将someData放入了buffers中,如果你读取那些数据,它将无法匹配WebGL中的内容。

    请注意上面的代码是伪代码,例如我没有提供gl.bufferSubData的包装器。

    WebGL2

    在WebGL2中有一个函数gl.getBufferSubData,可以让您读取缓冲区的内容。请注意,即使它基于OpenGL ES 3.0,WebGL2也不支持gl.mapBuffer,因为没有一种高效且安全的方法来公开该函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接