opengl 对多个着色器效果使用单个FrameBuffer会导致伪像

js4nwp54  于 2022-11-04  发布在  其他
关注(0)|答案(3)|浏览(140)

我正在使用libGDX,并且已经创建了我自己的Sprite-class和渲染器(它在引擎盖下使用libGDX的SpriteBatch)。渲染器相当“聪明”,它按照层/着色器/纹理/混合对精灵进行排序,并且精灵可以包含子元素。
现在我正在尝试添加对FrameBuffers的支持,我遇到了一个小问题。
我试图通过着色器添加多个后期处理效果,到我的游戏中的“根”精灵。
1.将根Sprite渲染到FBO中(背景和所有实体)
1.对同一FBO呈现“漩涡”效果
1.对相同的FBO渲染光晕效果
1.将水平模糊渲染到同一FBO
1.将垂直模糊渲染到同一FBO
1.通过Sprite将FBO的最终结果渲染到屏幕中
这一切都很简单,每个效果都有自己的Sprite-object。它们通过setLayer(int)分层,纹理/FBO/着色器通过setTexture(纹理)/ setTarget(纹理)/ setShader(着色器)设置。
我尝试并希望使用相同的纹理作为结果和目标。例如:

Texture fbo = Video.newTarget();

...

bloom.setTexture(fbo);
bloom.setTarget(fbo);

blurH.setTexture(fbo);
blurH.setTarget(fbo);

....

如果我以这种方式使用相同的FBO,我会在最终图像中看到一些难以描述的奇怪伪影。我要么在纹理中的某个地方得到一些奇怪的线条,要么只是一些奇怪的扭曲。
如果我为每种效果创建一个单独的FBO,一切都会很好。
例如:

Texture fbo1, fbo2, fbo3, fbo4;

...

bloom.setTexture(fbo1);
bloom.setTarget(fbo2);

blurH.setTexture(fbo2);
blurH.setTarget(fbo3);

...

如果可能的话,我真的希望避免这种情况,因为它会导致代码混乱,并损害性能。
我真的不太精通OpenGL/GLSL(我甚至不太了解渲染管道...:),但是,有人知道是什么可能导致这些伪像从我的解释?
我也想过有两个FBO和“乒乓球”之间,但由于某种原因,所有我看到的是黑色的...现在...:)我将不得不更多的实验。

gxwragnw

gxwragnw1#

您的问题来自于管道中存在相关的处理步骤。
将根Sprite渲染到FBO中(背景和所有实体)
呈现“漩涡”效果
然后,您将使用相同的FBO执行以下操作:
呈现开花效果
如果您的GPU驱动程序尚未完成处理您在绽放效果中覆盖的所有内容,则您在漩涡效果步骤中已完成的所有内容。
最好的方法是将您的流水线分解为独立的阶段,即使这意味着要使用多个FBO。
从我的Angular 来看如果你不需要原始的FBO,如果所有的效果都需要输入相同的纹理大小

Render the scene in FBO A.
Render Swirl effect in FBO B.
Render Bloom in FBO A using the color texture from FBO B.
Render Vertical Blur in FBO B using the color texture from FBO A.
....
d8tt03nd

d8tt03nd2#

OpenGL ES不支持同时阅读同一个纹理,这是你在第一个例子中所做的。你需要两个FBO,你可以在它们之间乒乓。

Texture fbo1, fbo2;

...

bloom.setTexture(fbo1);
bloom.setTarget(fbo2);

blurH.setTexture(fbo2);
blurH.setTarget(fbo1);

...
tcbh2hod

tcbh2hod3#

我有一个非常相似的问题,我很高兴我发现这个主题,这是一个痛苦,我试图调试我的glsl代码这么长时间...
我在使用一个带有单一缓冲区的递归着色器进行元胞自动机计算时,也遇到了同样的问题。我使用libgdx时遇到的问题是:

  • 从左下角到右上角的对角线伪影线
  • 每256 px水平/垂直伪像线

我通过交换每个帧的缓冲区来修复它

private void swapBuffers() {
    FrameBuffer tmp = buffer1;
    buffer1 = buffer2;
    buffer2 = tmp;
}

相关问题