可以从WebGL纹理对象轻松创建HTML图像元素吗?

可以从WebGL纹理对象轻松创建HTML图像元素吗?,webgl,Webgl,我想获取一个已渲染的WebGLTexture对象,并使用它创建一个HTML图像元素。目标是显示屏幕外渲染过程的结果,以便进行调试。这应该比将纹理渲染到全屏四边形(我当前的调试方法)容易得多 在WebGL中,从图像元素创建纹理非常容易: var image = new Image(); image.src = "myImg.jpg"; // image loads... var texture = gl.createTexture(); gl.bindTexture(texture); gl.

我想获取一个已渲染的WebGLTexture对象,并使用它创建一个HTML图像元素。目标是显示屏幕外渲染过程的结果,以便进行调试。这应该比将纹理渲染到全屏四边形(我当前的调试方法)容易得多

在WebGL中,从图像元素创建纹理非常容易:

var image = new Image();
image.src = "myImg.jpg";

// image loads...

var texture = gl.createTexture();
gl.bindTexture(texture);
gl.texImage2D(_gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, image);
图像加载和解码是完全照顾你

有没有一种同样简单的方法来做相反的事情?i、 e:

// This doesn't work
var img = new Image(texture);

// But maybe this could
var img = createImageFromTexture(texture);

function createImageFromTexture(texture) {
    // ... some combination of tricks ...
}

如果有一种方法可以做到这一点,我相信它在调试之外的环境中会很有用。我会继续看我是否能找到一种方法来实现这一点,但我觉得以前一定有人尝试过这一点。

WebGL上下文是一个画布,有几种有很好文档记录的方法可以从画布中获取图像,因此基本方法如下所示:

  • 在全屏(好的,全画布)四边形上绘制纹理。会的 最好先调整画布的大小,使画布具有 与尝试绘制的纹理图像的1:1像素比率
  • 使用类似的方法获取图像数据 在画布外
    如果您只想实际保存图像,可能需要将其发送到服务器进行处理,但是,如果您只是希望在呈现图像的同一页面上显示图像,则可以设置为
    img
    标记的
    src
    属性提供的数据URI,并且它应该正确显示。

    下面是一个与toDataURL()一起运行node.js服务器的示例要将多个图像直接传输到磁盘,请执行以下操作:

    您可以创建一个以纹理为背景的图像,然后使用从帧缓冲区读取原始像素数据。获得数据像素后,可以使用将其复制到二维画布。然后,可以通过将图像的src属性设置为来构造图像


    我在寻找方法时看到了这一点:你找到方法了吗?我正在努力使用第二步的方法。从WebGL画布实际获取图像。我现在得到的只是一个完全半透明的.png图像。我需要在画布中设置一些我没有设置的东西吗?虽然这确实有效,但它似乎是一个非常低效的解决方案。有更好的API吗?你在哪里使用这个API的结果?画布能工作吗,而不是用它来制作img?另一个要研究的选项是使用ImageData和CreateMageBitmap来创建ImageBitmap,而不是img。内容是动态生成的,但在其他情况下是静态的。我使用单个WebGL上下文为不同的设置生成一组预览。按钮显示预览。从您的推荐开始,我实际上找到了
    canvas.toBlob
    ,然后使用
    URL.createObjectURL
    可以显著提高性能。将测试并可能发布一个好的答案。是的,
    toBlob
    将是对支持它的浏览器的改进。它将允许主线程在编码图像时处理其他任务。它仍然需要一个图像编码和一个分配来保存编码后的图像。如果您可以将
    img
    s更改为
    canvas
    es,并
    putImageData
    将图像数据放入画布,这可能是最大的改进。
    function createImageFromTexture(gl, texture, width, height) {
        // Create a framebuffer backed by the texture
        var framebuffer = gl.createFramebuffer();
        gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
    
        // Read the contents of the framebuffer
        var data = new Uint8Array(width * height * 4);
        gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
    
        gl.deleteFramebuffer(framebuffer);
    
        // Create a 2D canvas to store the result 
        var canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        var context = canvas.getContext('2d');
    
        // Copy the pixels to a 2D canvas
        var imageData = context.createImageData(width, height);
        imageData.data.set(data);
        context.putImageData(imageData, 0, 0);
    
        var img = new Image();
        img.src = canvas.toDataURL();
        return img;
    }