当前位置: 首页 > 知识库问答 >
问题:

对多个着色器效果使用单个帧缓冲区会导致瑕疵

廉学潞
2023-03-14

我正在使用libGDX,并创建了自己的Sprite类和渲染器(在引擎盖下使用libGDX的SpriteBatch)。渲染器非常“智能”,它按层/着色器/纹理/混合对精灵进行排序,精灵可以包含子对象。

现在我试图添加对FrameBuffers的支持,我有一个小问题。

我试图通过着色器向游戏中的“根”精灵添加多个后期处理效果。

  1. 将根精灵渲染为FBO(背景和所有实体)

这一切都很简单,每个效果都有自己的Sprite对象。它们通过setLayer(int)分层,纹理/FBO/着色器通过setTexture(Texture)/setTarget(Texture)/setShader(Shader)设置。

我尝试并希望使用相同的纹理作为结果和目标。例如。:

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和“乒乓”,但出于某种原因,我看到的都是黑色的...目前...:)我将不得不对此进行更多的实验。

共有3个答案

葛霄
2023-03-14

我有一个非常类似的问题,我很高兴我找到了这个主题,这是一个痛苦的,我试图调试我的glsl代码这么长时间。。。

我用一个带有单个缓冲区的递归着色器进行细胞自动机计算,它也有同样的问题。我与libgdx的合作成果包括:

  • 从左下到右上的对角线人工制品线
  • 每256px水平/垂直人造线条

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

private void swapBuffers() {
    FrameBuffer tmp = buffer1;
    buffer1 = buffer2;
    buffer2 = tmp;
}
曹华荣
2023-03-14

OpenGL ES不支持同时对同一纹理进行读写,这就是第一个示例中所做的。你需要两个FBO,你可以在他们之间打乒乓球。

Texture fbo1, fbo2;

...

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

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

...
慕阳伯
2023-03-14

您的问题源于管道中存在依赖的处理步骤。

将根精灵渲染为FBO(背景和所有实体)

渲染“漩涡”-效果

然后您使用相同的FBO来执行

渲染花朵效果

如果您的GPU驱动程序尚未完成处理您在绽放效果中覆盖的所有内容,则您在漩涡效果步骤中所做的所有内容。

最好的方法是将你的管道分成独立的阶段,即使这意味着使用多个FBO。

从我的角度来看,如果你不需要原始的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.
....
 类似资料:
  • 在DirectX中,您可以有单独的渲染目标和深度缓冲区,因此可以绑定渲染目标和一个深度缓冲区、执行一些渲染、移除深度缓冲区然后使用旧的深度缓冲区作为纹理进行更多渲染。 你会如何在opengl中做到这一点?根据我的理解,您有一个帧缓冲区对象,其中包含颜色缓冲区和可选的深度缓冲区。我不认为我可以同时绑定多个帧缓冲器对象,我是否必须在每次更改时(可能一帧几次)重新创建帧缓冲器对象?普通的 opengl

  • 我正在使用JOGL,但这个问题一般适用于OpenGL。似乎存在类似的问题,但它们要么针对GLSL代码,要么与复制帧缓冲区的内容有关,要么是一般建议-使用帧缓冲区对象,而不是。 我正在做一些阴影映射。如何使用帧缓冲对象将深度通道直接渲染到纹理? 能否请你贴一段初始化纹理和帧缓冲对象的代码,以及渲染场景前初始化一切的代码? 目前,我使用<code>glCopyTexSubImage2D<code>。我

  • 注意 最后一次构建:2014年1月20日下午18:00。 这章的源代码能够在assetts folder找到。 http://labs.qt.nokia.com/2012/02/02/qt-graphical-effects-in-qt-labs/ http://labs.qt.nokia.com/2011/05/03/qml-shadereffectitem-on-qgraphicsview/

  • 他们没有提到的是如何首先将两个纹理传递给着色器。 以前我 所以现在我 如何将大小不同的纹理数组传递给GLSL? 将多个纹理从OpenGL传递到GLSL着色器 GLSL中的多个纹理-只有一个有效 (这是家庭作业,所以请用最少的代码片段回答(如果有的话)。谢谢!) 如果做不到这一点,有人有茶具吗?

  • 目前,我有一个OBJ加载程序,可以加载必要的OBJ,解析材质,并在必要时绑定纹理。 但是,我需要澄清,当顶点指针在刚刚绑定的VBO中移动时,是否可以绑定多个纹理。我的意思是:我想在一个VBO中跨不同网格放置多个材质。研究告诉我需要使用着色器,但没有指定如何在VBO中间加载它们。 我试图尽量减少绘制调用和VBOs的数量,同时(希望)尽可能远离多纹理。任何帮助都非常感谢! 当前绘图代码:

  • 这是我试图执行的主要程序: 但是,我看到的不是纹理而是白色矩形。如果我在屏幕上渲染,我会得到预期的结果(因此渲染代码应该没有问题)。这是FrameBuffer类: 其他一切都经过测试,所以问题应该在主程序的逻辑或帧缓冲区中。 顺便说一下,视口大小iz与窗口大小完全相同。