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

WebGL异步/顺序绘制纹理时旧纹理消失问题求助

解决WebGL绘制新纹理时旧纹理消失的问题

问题根源

WebGL是即时渲染模式,默认每次绘制前若执行gl.clear(gl.COLOR_BUFFER_BIT)会清空整个颜色缓冲区,导致之前的绘制内容丢失;另外如果绘制逻辑未限制渲染区域,新纹理会覆盖整个画布,也会造成旧内容消失。

具体解决方案

1. 仅初始化时清除画布

把画布清除操作移到初始化阶段,后续绘制新纹理时不再执行清除:

// 初始化函数(仅执行一次)
function initWebGL() {
  const gl = canvas.getContext('webgl');
  // 设置清除颜色并清空画布
  gl.clearColor(0, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
  // 开启混合(若图片带透明通道,保证叠加效果)
  gl.enable(gl.BLEND);
  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
  // 其他初始化:编译着色器、创建缓冲区等
  return gl;
}

// 绘制单张纹理的函数(每张图片加载完成后调用)
function drawTexture(gl, texture, x, y, width, height) {
  // 绑定目标纹理
  gl.bindTexture(gl.TEXTURE_2D, texture);
  // 传递纹理位置、尺寸等参数给着色器
  const program = gl.getParameter(gl.CURRENT_PROGRAM);
  gl.uniform2f(gl.getUniformLocation(program, 'u_position'), x, y);
  gl.uniform2f(gl.getUniformLocation(program, 'u_size'), width, height);
  // 绘制纹理对应的四边形
  gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}

2. 通过着色器限制渲染区域

修改顶点着色器,确保新纹理仅渲染到指定位置,不覆盖整个画布:

attribute vec2 a_position; // 纹理局部坐标(0,0)到(1,1)
attribute vec2 a_texCoord;
uniform vec2 u_resolution; // 画布分辨率
uniform vec2 u_position;   // 纹理左上角像素位置
uniform vec2 u_size;       // 纹理像素尺寸
varying vec2 v_texCoord;

void main() {
  // 将局部坐标转换为WebGL裁剪空间坐标(-1到1)
  vec2 pixelPos = u_position + a_position * u_size;
  vec2 clipSpace = (pixelPos / u_resolution) * 2.0 - 1.0;
  clipSpace.y = -clipSpace.y; // 翻转Y轴,匹配画布坐标系
  gl_Position = vec4(clipSpace, 0.0, 1.0);
  v_texCoord = a_texCoord;
}

3. 异步加载与叠加绘制流程

每张图片加载完成后创建纹理,调用绘制函数叠加到画布对应位置:

const imageUrls = ['img1.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg'];
const positions = [[0,0], [200,0], [0,200], [200,200]]; // 四张图的拼接位置

imageUrls.forEach((url, index) => {
  const img = new Image();
  img.crossOrigin = 'anonymous';
  img.onload = () => {
    // 创建并配置WebGL纹理
    const texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    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);
    // 绘制到指定位置
    const [x, y] = positions[index];
    drawTexture(gl, texture, x, y, img.width, img.height);
  };
  img.src = url;
});

关键注意点

  • 禁止在每次绘制前调用gl.clear,仅初始化时执行一次。
  • 若使用透明图片,必须开启混合模式保证叠加效果。
  • 着色器需正确计算纹理渲染位置,避免覆盖整个画布。

内容的提问来源于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.22 05:45:34