iOS 上的 LibGDX FrameBuffer 怪癖
Posted
技术标签:
【中文标题】iOS 上的 LibGDX FrameBuffer 怪癖【英文标题】:LibGDX FrameBuffer quirk on iOS 【发布时间】:2015-05-05 08:27:30 【问题描述】:我为文字游戏创建了动态纹理并将其保存在 FrameBuffer 中。然后我使用由该 FrameBuffer 支持的 TextureRegions 绘制到屏幕上。此代码在 android 上运行良好,但我在 ios 上遇到问题。
您可以看到下面的屏幕截图,左下角绘制了 FrameBuffer 内容 - 一切都很好。
但是,如果我返回 iOS 主屏幕,我会处理 FrameBuffer,然后根据需要重新创建并重绘所有内容到 FrameBuffer。然后 FrameBuffer 的内容似乎是屏幕的部分翻转镜像。
我尝试在每一帧上处理和重新创建 FrameBuffer 以查看会发生什么。同样,除非我返回 iOS 主屏幕,否则这会完美运行,之后 FrameBuffer 的内容不正确。
然后我尝试减小 FrameBuffer 的大小并在多个 FrameBuffer 上绘图。如果我这样做,它会再次正常工作,除非我返回 iOS 主屏幕。但是,在这种情况下,只有第一个创建的 FrameBuffer 损坏了,所有后续的缓冲区都很好。
然后我尝试总是先创建一个 1x1px 帧缓冲区,但我从来没有画过任何东西,这解决了我的问题....但是为什么!?我从 iOS 主屏幕返回后创建的第一个 FrameBuffer 似乎没有按预期工作,但之后的每个 FrameBuffer 都很好。看起来它总是试图在我创建的第一个 FrameBuffer 上绘制屏幕。
FrameBuffer的创建和绘制代码如下:
private static FrameBuffer getFrameBuffer(boolean newRequired)
if (newRequired || frameBuffers.size == 0)
FrameBuffer frameBuffer;
try
frameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, getFrameBufferSize(), getFrameBufferSize(), false);
catch (Exception e)
frameBuffer = new FrameBuffer(Format.RGBA4444, getFrameBufferSize(), getFrameBufferSize(), false);
frameBuffer.begin();
Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
frameBuffer.end();
frameBuffers.add(frameBuffer);
// Set up the camera correctly for the frame buffer
OrthographicCamera camera = new OrthographicCamera(frameBuffer.getWidth(), frameBuffer.getHeight());
camera.position.set(frameBuffer.getWidth() * 0.5f, frameBuffer.getHeight() * 0.5f, 0);
camera.update();
spriteBatch.setProjectionMatrix(camera.combined);
return frameBuffers.get(frameBuffers.size - 1);
private static TextureRegion getTextureUsingGpu(String letter, Bubble.BubbleType bubbleType)
if (!enabled)
return null;
TextureRegion tx = getBlockImage(letter, bubbleType);
int width = (int) (tx.getRegionWidth() * LayoutManager.getShortEdge() / 1080 * LayoutManager.getScaling());
int height = (int) (tx.getRegionHeight() * LayoutManager.getShortEdge() / 1080 * LayoutManager.getScaling());
if (nextTextureX + width + PADDING > getFrameBufferSize())
nextTextureX = PADDING;
nextTextureY = nextRowY + PADDING;
if (nextTextureY + height + PADDING > getFrameBufferSize())
getFrameBuffer(true);
nextRowY = PADDING;
nextTextureY = PADDING;
FrameBuffer fb = getFrameBuffer(false);
fb.begin();
spriteBatch.begin();
tx.flip(false, !tx.isFlipY());
spriteBatch.disableBlending();
spriteBatch.draw(tx, nextTextureX, nextTextureY, width, height);
spriteBatch.enableBlending();
// Drawing Code Removed
spriteBatch.end();
fb.end();
TextureRegion textureRegion = new TextureRegion(fb.getColorBufferTexture(), nextTextureX, nextTextureY, width, height);
textureRegion.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
cacheTexture(letter, textureRegion);
nextTextureX += width;
nextRowY = Math.max(nextRowY, nextTextureY + height);
return textureRegion;
【问题讨论】:
【参考方案1】:如果您从resize
或resume
方法调用getFrameBuffer
或getTextureUsingGpu
,那就是问题所在。在 iOS 上,resize
和 resume
不一定会在 OpenGL 准备好恢复之前调用,因此在此处执行与 OpenGL 直接相关的任何操作都是不安全的,例如创建 ShaderPrograms、加载纹理或创建 FrameBuffers。我在游戏中修复了这个问题,方法是使用resume
设置成员布尔值,并使用它将新帧缓冲区的创建推迟到render
方法。
【讨论】:
感谢您的提示。我刚刚修改了所有已解决问题的代码 - 现在我无法测试您所说的是否正确。也就是说,我的重构包括按照您的建议进行操作,所以我推测您是正确的。在需要将其绘制到屏幕之前,我不再向 FrameBuffer 绘制任何内容。以上是关于iOS 上的 LibGDX FrameBuffer 怪癖的主要内容,如果未能解决你的问题,请参考以下文章
libGDX:FrameBuffer 大小限制 == 最大纹理大小?