WebGL渲染到自定义帧缓冲纹理后显示黑屏问题求助
WebGL自定义帧缓冲渲染黑屏问题排查与解决
需求说明
需要实现的功能如下:
- 第一遍渲染流程中将场景绘制到自行创建的framebuffer上
- 提取绑定到该自定义帧缓冲的纹理,绘制到平面后输出到屏幕
- 后续基于该流程实现后处理效果
当前现象
仅使用默认帧缓冲时场景可以正常显示,显示效果如下:
切换到自定义帧缓冲双Pass渲染后仅显示黑屏,已通过gl.LINE_STRIP验证屏幕平面放置位置正确,排除几何绘制错误。
核心问题排查与修复方案
结合给出的代码,黑屏问题由以下几个常见错误导致,按优先级修复即可:
1. 纹理未绑定到对应纹理单元
第二Pass绘制屏幕平面之前,只给screenTexture统一值赋值了纹理单元0,但没有把帧缓冲对应的纹理主动绑定到gl.TEXTURE0单元,采样器无法读取到正确的纹理数据,所以返回全黑。
修复代码,在gl.uniform1i(screenTexture, 0);之前添加如下内容:
gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, texture);
2. 帧缓冲尺寸参数错误
代码中使用canvas.clientWidth/canvas.clientHeight作为帧缓冲尺寸,这两个是canvas的CSS显示尺寸,WebGL渲染使用的是canvas的width和height属性,两者不一致时会导致渲染到帧缓冲的画面偏移、拉伸甚至超出缓冲范围,画面被裁剪为空。
修复代码,把texImage2D和renderbufferStorage中的尺寸参数替换:
// 纹理尺寸设置 gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGB, canvas.width, // 替换原canvas.clientWidth canvas.height, // 替换原canvas.clientHeight 0, gl.RGB, gl.UNSIGNED_BYTE, null ); // 渲染缓冲尺寸设置同理 gl.renderbufferStorage( gl.RENDERBUFFER, gl.DEPTH_STENCIL, canvas.width, canvas.height );
3. 纹理缺少包裹参数设置
WebGL默认的纹理包裹参数是gl.REPEAT,非2次幂尺寸的纹理使用REPEAT会导致采样失效,虽然你已经设置了滤波参数为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);
可选优化建议
- 屏幕平面的缓冲创建不需要放在每帧渲染的第二Pass里,放到初始化阶段一次性创建即可,避免每帧重复创建缓冲导致性能损耗。
- 排查问题时可以在片段着色器里临时输出固定颜色或者纹理坐标颜色,验证是采样问题还是顶点绘制问题,比如先写
gl_FragColor = vec4(TexCoords, 0.0, 1.0);,如果显示彩色渐变就说明顶点和纹理坐标是正常的,问题出在纹理采样阶段。
内容的提问来源于stack exchange,提问作者Ronan Quigley
相关产品推荐
相关产品推荐

