我正在开发一个WebGL OpenGL ES项目,该项目将我的场景渲染为纹理,然后使用该纹理渲染到窗口。
我注意到这会在纹理边缘产生奇怪的闪烁。当我将项目恢复为直接渲染到窗口时,闪烁消失了。
将FBO设置为与窗口相同的大小,并将纹理绘制到像素的窗口像素。
是什么导致这种情况发生?它可以修复吗?我在FBO纹理上使用GL_NEAREST,在所有其他纹理上使用GL_LINEAR。我宁愿不使用GL_CLAMP_TO_EDGE,因为这会导致其他问题。
帧缓冲区创建
/* Returns true if a framebuffer object is created */
Display.prototype.createFramebuffer = function(name) {
var gl = this.gl; // Sanity Save
var size = 1024;
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
fb.width = size;
fb.height = size;
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, fb.width, fb.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
var rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, fb.width, fb.height);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);
if(gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) { return false; }
this.fbo[name] = {fb: fb, rb: rb, tex: tex};
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
return true;
};
在绘制场景之前
/* Draw Geometry */
gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo.world.fb); // Enable world framebuffer
gl.viewport(0, 0, this.window.width, this.window.height); // Resize to canvas
gl.clearColor(0.5, 0.5, 0.5, 1.0); // Opaque grey backdrop
答案 0 :(得分:0)
在向正确的方向推进(以及大量的试验和错误)后,我发现了问题。
发生这种情况的原因是因为渲染到FBO纹理时禁用了硬件抗锯齿。为了解决这个问题,你需要实现自己的AA。
为了解决这个问题,我尝试了一个原始的MSAA后期着色器,并将我的FBO渲染升级到窗口分辨率的2倍,并将闪烁降低到几乎无法察觉的水平。
FXAA可能是另一个很好的解决方案,但我无法让它为我个人工作。
如果有更好的方法,请告诉我!