【问题标题】:Texture Coordinates are slightly off when rendering to FBO texture渲染到 FBO 纹理时,纹理坐标略有偏差
【发布时间】:2017-03-07 14:11:03
【问题描述】:

我正在开发一个 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

【问题讨论】:

  • 您的 FBO 设置如何?与屏幕大小和格式相同?您使用的是 OpenGL 还是 OpenGL-es?显示相关代码。
  • @BDL 添加了设置代码。它与屏幕的大小和格式相同。 WebGL 使用 OpenGL ES。
  • 所以它实际上是WebGL?所有三个版本,Desktop-OpenGL、OpenGL-es 和 WebGL 都有自己的局限性和限制。用正确的问题标记您的问题可确保您不会得到不适用于您的环境的答案。
  • 是的,我在问题的第一行说 WebGL,呵呵。不知道我需要将其标记为特定的 opengl 版本。我只是使用了建议的。
  • 如果你关闭抗锯齿,你会在画布上得到同样的结果吗? canvas.getContext("webgl", {antialias: false});

标签: javascript webgl


【解决方案1】:

在朝着正确的方向推进(以及大量的试验和错误)之后,我发现了问题。

发生这种情况的原因是在渲染到 FBO 纹理时禁用了硬件抗锯齿功能。为了修复它,您需要实现自己的 AA。

为了为我的项目解决这个问题,我尝试了一个粗略的 MSAA 后期着色器,并结合将我的 FBO 渲染放大到 2 倍窗口分辨率,从而将闪烁减少到几乎不明显的水平。

FXAA 可能是另一个不错的解决方案,但我个人无法使用它。

如果有更好的方法,请告诉我!

【讨论】:

  • 我会换一种说法。问题是无论你在做什么都是抗锯齿敏感的。我想我会尽量让它不敏感,而不是如何在 FBO 上进行抗锯齿。
  • @gman 根据我的阅读,WebGL 在渲染到 FBO 纹理时不支持抗锯齿。此信息的一些来源有点旧(1-2 年)。如果你能找到一些相反的可靠参考,我很乐意找到一种更好的方法来处理这个问题。我不喜欢使用我自己的 AA 方法,因为它们效率低下。我也非常感谢您的帮助。我觉得我经常在这里被完全忽视。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-16
  • 1970-01-01
  • 1970-01-01
  • 2014-06-19
相关资源
最近更新 更多