Android 在帧缓冲区上绘制的LibGDX纹理比原始纹理更暗

Android 在帧缓冲区上绘制的LibGDX纹理比原始纹理更暗,android,opengl-es,libgdx,alpha,Android,Opengl Es,Libgdx,Alpha,更新1 正如您可以看到的,在帧缓冲区上绘制的LibGDX纹理,与直接在SpriteBatcher上绘制的纹理相比,SpriteBatcher上的纹理比原始纹理更暗 左侧为原始图像,比手机1080x1920屏幕小50% 中间部分直接从SpriteBatch上的TextureRegion绘制,并水平镜像,以便更好地与左右图像进行比较。它有点失真,但我启用了线性过滤,正如您在代码中看到的: texture = new Texture("texture.png"); texture.setFilter

更新1

正如您可以看到的,在帧缓冲区上绘制的LibGDX纹理,与直接在SpriteBatcher上绘制的纹理相比,SpriteBatcher上的纹理比原始纹理更暗

左侧为原始图像,比手机1080x1920屏幕小50%

中间部分直接从SpriteBatch上的TextureRegion绘制,并水平镜像,以便更好地与左右图像进行比较。它有点失真,但我启用了线性过滤,正如您在代码中看到的:

texture = new Texture("texture.png");
texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
image = new TextureRegion(texture, 0, 0, 1024, 1024);

batcher.begin();
batcher.draw(image, 0, 0, screenWidth, screenHeight);
batcher.end();
右部分首先在帧缓冲区上绘制TextureRegion,然后在SpriteBatch上绘制,如以下代码所示:

texture = new Texture("texture.png");
texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
image = new TextureRegion(texture, 0, 0, 1024, 1024);

pixmap = new FrameBuffer(Pixmap.Format.RGBA8888, screenWidth, screenHeight, false);
pixmapregion = new TextureRegion(pixmap.getColorBufferTexture(), screenWidth, screenHeight);

pixmap.begin();
batcher.begin();
batcher.draw(image, 0, 0, screenWidth, screenHeight);
batcher.end();
pixmap.end();

batcher.begin();
batcher.draw(pixmapregion , 0, 0, screenWidth, screenHeight);
batcher.end();
正如你们所看到的,它比直接从纹理绘制的图像略暗。当我使用着色器绘制它时,与使用着色器绘制的纹理相比,结果非常混乱

所以真正的问题是帧缓冲区如何处理弄乱它的纹理,所以它不能用于着色器。我需要先在pixmap上绘制,这样我可以混合两个透明的帧缓冲区。我一直认为问题出在着色器上,我花了3天时间才找到问题所在,所以如果有人能帮助我,我将非常感激!)

注意:我尝试在帧缓冲区上绘制时启用混合,首先用Gdx.gl.glClear(GL20.gl_COLOR_BUFFER_BIT | GL20.gl_DEPTH_BUFFER_BIT)将其清除;但没什么不同

更新2

看起来我应该在使用帧缓冲区绘制时设置一种GL混合,在使用帧缓冲区绘制时设置秒混合,但我还无法获得正确的组合

老问题

左图是在Photoshop中制作的,具有alpha透明度,但我放置了黑色背景,这样可以看得更清楚。右图是android屏幕上的屏幕截图。这是我的代码,我首先在pixmap上绘制纹理,然后在屏幕上绘制该pixmap,纹理质量非常差,正如您所看到的,alpha通道非常扭曲

texture = new Texture("drop-blue.png");
texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
image = new TextureRegion(texture, 0, 0, 1024, 1024);

pixmap = new FrameBuffer(Pixmap.Format.RGBA8888, screenWidth, screenHeight, false);
pixmapregion = new TextureRegion(pixmap.getColorBufferTexture(), screenWidth, screenHeight);

pixmap.begin();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batcher.begin();
batcher.draw(image, screenWidth/2 - 512, screenHeight/2 - 512, 1024, 1024);
batcher.end();
pixmap.end();

batcher.begin();
batcher.draw(pixmapregion, 0, 0, screenWidth, screenHeight);
batcher.end();

这是正常的,混合是如何工作的。将具有透明度的纹理渲染到具有透明度的帧缓冲区上,然后渲染到屏幕上(backbuffer)。这会导致混合应用两次

让我们通过观察单个像素如何从纹理到fbo再到屏幕来了解实际发生的情况。首先,通过查看渲染到FBO时发生的情况:

  • 假设纹理中的像素是
    [r:0.5,g:1.0,b:0.0,a:0.75]
    ,这将是我们的源像素
  • 当您将其渲染到帧缓冲区时,目标像素最初是
    [r:0.0,g:0.0,b:0.0,a:0.0]
    ,这是您的
    glClearColor
  • 默认情况下,混合函数用于源
    SRC_ALPHA
    和目标
    ONE_减\u SRC_ALPHA
  • 当渲染到FBO时,这将导致:
    [r:0.75*0.5,g:0.75*1.0,b:0.75*0.0,a:0.75*0.75]+[r:(1-0.75)*0.0,g:(1-0.75)*0.0,b:(1-0.75)*0.0,a:(1-0.75)*0.0]
    这将导致
    [r:0.375,g:0.75,b:0.0,a:0.5625]
现在,让我们看看将FBO渲染到屏幕时会发生什么:

  • 源像素是:
    [r:0.375,g:0.75,b:0.0,a:0.5625]
  • 目标像素(屏幕的glClearColor)是
    [r:0,g:0,b:0]
    (无alpha通道)
  • 因此,混合结果将是:
    [r:0.211,g:0.422,b:0.0]
    (无alpha通道)
注意结果是如何变得越来越暗的。这是因为它与原始颜色混合,在您的例子中,原始颜色是黑色。如果你使用白色,它实际上会变得越来越亮

如果您不喜欢此行为,则可以使用
Batch\disableBlending()
完全禁用混合。如果您只想混合一次,则可以使用不带alpha通道的FBO(例如,
RGB888
而不是
RGBA888
)。或者,如果要自定义行为,则可以使用不同的混合函数,使用
Batch\setBlendFunction


顺便说一句,当我打字的时候,我记得我以前做过。这里有几乎相同的问题和答案:

图像在哪里?对不起,我忘了添加链接…您的图像是RGBA8888格式的吗?尝试Gdx.gl.glClear(GL20.gl_COLOR_BUFFER_BIT | GL20.gl_DEPTH_BUFFER_BIT);和spritebatch.enablembling();spritebatch.setBlendFunction(gl.BLEND\u SRC\u ALPHA,gl.BLEND\u ONE\u减去\u SRC\u ALPHA);是的,在Photoshop中,我将web图像保存为24位,并选中了透明度,据我所知,这应该是RGBA8888。我还尝试启用混合并设置混合函数,但没有成功,同样的事情再次发生…:/对不起,我没有看到这个问题,我在谷歌上搜索了一下,但没有找到。在fbo上绘图时,我尝试了所有可能的混合组合,我发现setBlendFunction(GL20.GL_ONE_减去DST_ALPHA,GL20.GL_ONE)和setBlendFunction(GL20.GL_BLEND_SRC_ALPHA,GL20.GL_ONE)的效果最好。现在的问题是,当我用ShaderProgram绘制帧缓冲区时,它的行为真的很奇怪,在FBO上绘制纹理时,以及在屏幕上绘制FBO时,各种可能的混合组合。当我用着色器绘制纹理时,我不能得到同样的结果。如果你还有另一个问题,那就考虑打开另一个问题。嗯,当我只画一个PNG到FBO时,这种混合工作了,但是当我画多个PNG到FBO时,混合非常糟糕,透明的区域相互重叠,颜色变得扭曲。我尝试了各种可能的组合,将它们与屏幕不同部分的触摸事件混合在一起,但没有成功。在LibGDX中是否有帧缓冲区的替代方案?如果我想在fbo上绘制多个透明纹理(就像老问题中的图像上那样),并且它们经常相互重叠,我该怎么办。我把它们画在透明的纸上