更新1
正如你可以看到在FrameBuffer上绘制的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();
右边部分首先在FrameBuffer上绘制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();
就像你可以看到的,它比直接从纹理中绘制的图像更暗。当我使用着色器绘制它时,与使用着色器绘制的纹理相比,结果真的很糟糕。
所以真正的问题是FrameBuffer做什么来纹理它的混乱,所以它不能用着色器。我需要首先在pixmap上绘制它,所以我可以混合两个透明的FrameBuffers。一直以来我都认为问题出在着色器上,我失去了3天发现问题所在,所以如果有人能帮助我,我将非常感激! :)
注意:我尝试在FrameBuffer上绘图时启用混合,先用Gdx.gl.glClear清除它(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);但没有什么不同。
更新2
在绘制FrameBuffer时设置一种GL混合,并在绘制FrameBuffer时设置第二种混合看起来我应该做些什么,但我还是不能得到正确的组合... < / p>
旧问题
左图是在Photoshop中制作的,具有Alpha透明度,但我放置了黑色背景,因此可以更好地看到它。右图是从android屏幕拍摄的屏幕。这是我的代码,我首先在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();
答案 0 :(得分:1)
这是正常的,混合是如何工作的。您正在将具有透明度的纹理渲染到具有透明度的帧缓冲区上,然后将其渲染到屏幕上(后备缓冲区)。这会导致混合应用两次。
通过查看单个像素如何从纹理转换为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_MINUS_SRC_ALPHA
。[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]
[r:0, g:0, b:0]
(无alpha通道)[r:0.211, g:0.422, b:0.0]
(无alpha通道)注意结果如何变暗和变暗。这是因为它与原始颜色混合,在您的情况下是黑色。如果您使用例如白色然后它会变得更亮更明亮。
如果您不喜欢此行为,则可以使用Batch#disableBlending()
完全禁用混合。如果您只想混合一次,则可以使用不带Alpha通道的FBO(例如RGB888
而不是RGBA8888
)。或者,如果要自定义行为,则可以使用Batch#setBlendFunction
使用不同的混合函数。