You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过WebGL帧缓冲区异步拼接图像并保留已渲染内容?

WebGL异步拼接图像并保留历史渲染内容的问题

这是我此前问题《Draw textures to canvas async / in sequence deletes old textures》的后续,采用朋友推荐的不同方案。我刚接触WebGL,还请包涵。

我的目标

  • 异步加载图像
  • 将这些图像以并排“平铺”的方式渲染到单个WebGL画布上,每张图像包含指定其在画布中渲染位置的坐标
  • 每次异步加载图像后,将整个画布视为单个纹理,通过shader对整体纹理进行图像处理

使用帧缓冲区(framebuffer)

我的理解是可以创建帧缓冲区,将纹理渲染到其中,再将帧缓冲区渲染到目标纹理,最后将目标纹理渲染到屏幕。

// 首先创建帧缓冲区,以及要渲染到的目标纹理,并将纹理附加到帧缓冲区
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
const targetTexture = gl.createTexture();

gl.framebufferTexture2D(
    gl.FRAMEBUFFER,
    gl.COLOR_ATTACHMENT0,
    gl.TEXTURE_2D,
    targetTexture,
    0
);

我的思路是每次加载图像后,将其创建为纹理,启用顶点属性后调用drawArrays绘制到帧缓冲区,再解绑帧缓冲区调用drawArrays渲染到屏幕,但此处存在困惑:

// 假设我们现在有一个包含多个瓦片图片URL的数组:
tiles.forEach((tile) => {
  const image = new Image();
  image.onload = () => render(image, tile);
  image.src = tile.path;
});

function render(tileImage: HTMLImageElement, tile: Tile) {
    // 获取顶点数据的位置
    var positionLocation = gl.getAttribLocation(program, 'a_position');
    var texcoordLocation = gl.getAttribLocation(program, 'a_texCoord');

    // 创建缓冲区来存储二维裁剪空间的点
    var positionBuffer = gl.createBuffer();

    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    // 设置与图像尺寸相同的矩形(细节见问题附录)
    setRectangle(
        gl,
        tile.position.x,
        tile.position.y,
        tileImage.width,
        tileImage.height
    );

    // 为矩形提供纹理坐标
    var texcoordBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);

    gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array([
            0.0, 0.0,
            1.0, 0.0,
            0.0, 1.0,
            0.0, 1.0,
            1.0, 0.0,
            1.0, 1.0,
        ]),
        gl.STATIC_DRAW
    );

    // 创建纹理并绑定到WebGL上下文
    const texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);

    // 设置参数以支持任意尺寸的图像渲染
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

    // 将瓦片图像上传到纹理
    gl.texImage2D(
        gl.TEXTURE_2D,
        0,
        gl.RGBA,
        gl.RGBA,
        gl.UNSIGNED_BYTE,
        tileImage
    );

    // 获取uniform变量的位置
    var resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
    var textureSizeLocation = gl.getUniformLocation(program, 'u_textureSize');

    // 告知WebGL如何从裁剪空间转换为像素
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

    // 使用我们的着色器程序
    gl.useProgram(program);

    // 启用位置属性
    gl.enableVertexAttribArray(positionLocation);
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

    // 启用纹理坐标属性
    gl.enableVertexAttribArray(texcoordLocation);
    gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
    gl.vertexAttribPointer(texcoordLocation, 2, gl.FLOAT, false, 0, 0);

    // 设置分辨率和图像尺寸
    gl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height);
    gl.uniform2f(textureSizeLocation, 256, 256);

    // 绑定帧缓冲区并绘制——绘制到帧缓冲区?
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    gl.drawArrays(gl.TRIANGLES, 0, 6);

    // 解绑帧缓冲区并绘制——绘制到画布?
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    gl.drawArrays(gl.TRIANGLES, 0, 6);
}

实际运行时,每次加载新图像后,之前渲染的图像会消失。我查阅过相关讨论,但未找到针对简单2D图像异步渲染到WebGL画布的方案。此外,有人推荐先通过2D Canvas API将图像绘制到2D画布,再将其作为WebGL的单一纹理来源,但我不理解该方案的优势。

请问如何实现将这些图像异步拼接并渲染到单个WebGL画布中?

附录:

export function setRectangle(
    gl: WebGLRenderingContext,
    x: number,
    y: number,
    width: number,
    height: number
) {
    const x1 = x,
        x2 = x + width,
        y1 = y,
        y2 = y + height;

    gl.bufferData(
        gl.ARRAY_BUFFER,
        // prettier-ignore
        new Float32Array([
      x1, y1, 
      x2, y1, 
      x1, y2, 
      x1, y2, 
      x2, y1, 
      x2, y2]),
        gl.STATIC_DRAW
    );
}

内容的提问来源于stack exchange,提问作者Seth Lutske

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:50:01