如何正确使用LIBGDXFrameBuffer
How to use LIBGDX FrameBuffer correctly
这是我的第一个问题。我试图查看源代码 (link)
搜索 Whosebug 并阅读一些一般性解释。但是我不知道如何正确设置(或理解)它。
我不了解投影矩阵或大部分 GL 术语。
我不知道当你设置相机时会发生什么(camera.setToOrtho())当你应该更新相机时
或者何时设置批次的投影矩阵。到目前为止,我对它的唯一使用仅限于下面所示的 draw() 方法中使用的代码。
我有一个带有图层的基于图块的游戏。我想使用 FrameBuffer 将水层绘制到 TextureRegion。所以我以后可以尝试用着色器来操纵它。我认为这将是做到这一点的方法。
(我没有使用任何 "Scene2d" 或 "Tiled" classes)
Example of what the layer looks like
我如何绘制图层:
public void draw(OrthographicCamera camera) {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA,GL20.GL_ONE_MINUS_SRC_ALPHA); // [1]
BATCH.setProjectionMatrix(camera.combined);
BATCH.begin();
for (int i = 0; i < NUM_LAYERS; i++) {
if (RENDER[i]) {
if (SORT[i]) Collections.sort(LAYERS.get(i));
for (DrwDat dat: LAYERS.get(i)) { // [2]
dat.draw(BATCH);
}
}
}
BATCH.end();
}
1。不知道这是做什么的,但我似乎不需要它。
[2]. DrwDat 只是一个保存可绘制对象的 class。在这种情况下,这些是瓷砖。
好的。所以在绘制循环中,我放置了一个在绘制水层时调用的方法。目前
我想绘制应该在屏幕上显示的每个图块,而不是将它们绘制到缓冲区。然后:将缓冲区绘制到屏幕上。
问题:我可以在下面的 "renderFBO()" 方法中输入什么来使其工作?为什么?基本上让屏幕准确显示不使用 FrameBuffer
时会显示的内容
(当前代码纯粹是绝望,因为我尝试使用 youtube
看不懂就当作模板教程。)
private void renderFBO(OrthographicCamera camera, int layer) {
BATCH.end();
frameBuffer.begin();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
BATCH.begin();
camera.setToOrtho(false);
camera.position.set(FocusPoint.position.x,FocusPoint.position.y,0); // [3]
camera.update();
BATCH.setProjectionMatrix(camera.combined);
for (DrwDat dat: LAYERS.get(layer)) {
dat.draw(BATCH);
}
frameBuffer.end(); // [4]
BATCH.end();
camera.setToOrtho(false);
//BATCH.setProjectionMatrix(camera.combined);
BATCH.begin();
BATCH.draw(bufferTexture.getTexture(),0,0,Settings.SCREEN_W,Settings.SCREEN_H);
BATCH.end();
camera.position.set(FocusPoint.position.x,FocusPoint.position.y,0);
camera.update();
BATCH.setProjectionMatrix(camera.combined);
BATCH.begin();
}
[3]。 FocusPoint 只是相机跟随的一个点(例如:鼠标点击位置)
[4]。出于某种原因,framebuffer.end() 在 batch.end() 下方不会呈现任何内容。
下面是我如何初始化 FrameBuffer:
private FrameBuffer frameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888,Settings.SCREEN_W,Settings.SCREEN_H,false);
private TextureRegion bufferTexture = new TextureRegion(frameBuffer.getColorBufferTexture());
如果这太笼统了,我很抱歉。但任何帮助表示赞赏。我可以阅读的任何提示也会
很有帮助。
关于您的第 1 点:您不需要该行,因为 SpriteBatch 会自行管理混合并将覆盖您在调用 batch.begin()
.
之前设置的任何混合状态
关于您的第 4 点:像这样打乱它们,您根本就没有吸引 FBO。可能是您的 FBO 设置有问题或您绘制它的方式有问题,所以它无法正常工作,但像正常一样直接在屏幕上绘制会使它看起来像是在工作。
就像在您的示例中一样,这将假设它正在中断 batch.begin()
和 batch.end()
之间完成的现有绘图。所以它会在你的 begin()
和 end()
调用之间被调用,如下所示:
public void draw(OrthographicCamera camera) {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
BATCH.setProjectionMatrix(camera.combined);
BATCH.begin();
renderFbo();
BATCH.end();
}
无需摆弄相机来绘制帧缓冲区内容以覆盖整个屏幕。您可以使用单位投影矩阵和 OpenGL 将默认投影定义为 2 个单位宽和高,以 (0, 0) 为中心的知识。
您不需要结束和开始批处理。在切换渲染表面之前刷新它会更简单一些。
private final Matrix4 originalMatrixTemp = Matrix4();
private static final Matrix4 IDENTITY = Matrix4();
public void renderFbo() {
// Finish drawing anything queued before we switch the frame buffer.
batch.flush();
// Store the current Batch state for things we're going to temporarily change.
originalMatrixTemp.set(BATCH.getProjectionMatrix());
ShaderProgram originalShader = BATCH.getShaderProgram();
int originalBlendSrcFunc = BATCH.getBlendSrcFunc();
int originalBlendDstFunc = BATCH.getBlendDstFunc();
// No need to set up camera projection again.
// It was already set before calling this method.
// This ensures alpha is preserved in case you have overlapping translucent sprites.
BATCH.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE);
// Draw to FBO
frameBuffer.begin();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
for (DrwDat dat: LAYERS.get(layer)) {
dat.draw(BATCH);
}
BATCH.flush();
frameBuffer.end();
/* When you have a custom shader for rendering FBO contents, here's where
you would prepare it.
BATCH.setShader(waterFboShader);
waterFboShader.setUniformf("u_someUniformAttribute", someUniformAttribute);
etc.
*/
// Ensure we're drawing the frame buffer texture without modifying its color.
BATCH.setColor(Color.WHITE);
// Dimensions to the corners of the screen when using an identity matrix for
// projection. Negative height to flip vertically. (OpenGL image space and world
// space have opposite Y directions for some reason.)
BATCH.setProjectionMatrix(IDENTITY);
BATCH.draw(frameBuffer.getColorBufferTexture(), -1, 1, 2, -2);
BATCH.flush();
// Restore state from before this method was called.
BATCH.setShader(originalShader);
BATCH.setProjectionMatrix(originalMatrixTemp);
BATCH.setBlendFunction(originalBlendSrcFunc, originalBlendDstFunc);
}
存储原始矩阵时,您必须将其值复制到您自己的临时实例中,因为 SpriteBatch 会向您传递其自己的最终实例,其值在您应用单位矩阵时将被覆盖。
这是我的第一个问题。我试图查看源代码 (link) 搜索 Whosebug 并阅读一些一般性解释。但是我不知道如何正确设置(或理解)它。
我不了解投影矩阵或大部分 GL 术语。 我不知道当你设置相机时会发生什么(camera.setToOrtho())当你应该更新相机时 或者何时设置批次的投影矩阵。到目前为止,我对它的唯一使用仅限于下面所示的 draw() 方法中使用的代码。
我有一个带有图层的基于图块的游戏。我想使用 FrameBuffer 将水层绘制到 TextureRegion。所以我以后可以尝试用着色器来操纵它。我认为这将是做到这一点的方法。
(我没有使用任何 "Scene2d" 或 "Tiled" classes)
Example of what the layer looks like
我如何绘制图层:
public void draw(OrthographicCamera camera) {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA,GL20.GL_ONE_MINUS_SRC_ALPHA); // [1]
BATCH.setProjectionMatrix(camera.combined);
BATCH.begin();
for (int i = 0; i < NUM_LAYERS; i++) {
if (RENDER[i]) {
if (SORT[i]) Collections.sort(LAYERS.get(i));
for (DrwDat dat: LAYERS.get(i)) { // [2]
dat.draw(BATCH);
}
}
}
BATCH.end();
}
1。不知道这是做什么的,但我似乎不需要它。 [2]. DrwDat 只是一个保存可绘制对象的 class。在这种情况下,这些是瓷砖。
好的。所以在绘制循环中,我放置了一个在绘制水层时调用的方法。目前 我想绘制应该在屏幕上显示的每个图块,而不是将它们绘制到缓冲区。然后:将缓冲区绘制到屏幕上。
问题:我可以在下面的 "renderFBO()" 方法中输入什么来使其工作?为什么?基本上让屏幕准确显示不使用 FrameBuffer
时会显示的内容(当前代码纯粹是绝望,因为我尝试使用 youtube 看不懂就当作模板教程。)
private void renderFBO(OrthographicCamera camera, int layer) {
BATCH.end();
frameBuffer.begin();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
BATCH.begin();
camera.setToOrtho(false);
camera.position.set(FocusPoint.position.x,FocusPoint.position.y,0); // [3]
camera.update();
BATCH.setProjectionMatrix(camera.combined);
for (DrwDat dat: LAYERS.get(layer)) {
dat.draw(BATCH);
}
frameBuffer.end(); // [4]
BATCH.end();
camera.setToOrtho(false);
//BATCH.setProjectionMatrix(camera.combined);
BATCH.begin();
BATCH.draw(bufferTexture.getTexture(),0,0,Settings.SCREEN_W,Settings.SCREEN_H);
BATCH.end();
camera.position.set(FocusPoint.position.x,FocusPoint.position.y,0);
camera.update();
BATCH.setProjectionMatrix(camera.combined);
BATCH.begin();
}
[3]。 FocusPoint 只是相机跟随的一个点(例如:鼠标点击位置)
[4]。出于某种原因,framebuffer.end() 在 batch.end() 下方不会呈现任何内容。
下面是我如何初始化 FrameBuffer:
private FrameBuffer frameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888,Settings.SCREEN_W,Settings.SCREEN_H,false);
private TextureRegion bufferTexture = new TextureRegion(frameBuffer.getColorBufferTexture());
如果这太笼统了,我很抱歉。但任何帮助表示赞赏。我可以阅读的任何提示也会 很有帮助。
关于您的第 1 点:您不需要该行,因为 SpriteBatch 会自行管理混合并将覆盖您在调用 batch.begin()
.
关于您的第 4 点:像这样打乱它们,您根本就没有吸引 FBO。可能是您的 FBO 设置有问题或您绘制它的方式有问题,所以它无法正常工作,但像正常一样直接在屏幕上绘制会使它看起来像是在工作。
就像在您的示例中一样,这将假设它正在中断 batch.begin()
和 batch.end()
之间完成的现有绘图。所以它会在你的 begin()
和 end()
调用之间被调用,如下所示:
public void draw(OrthographicCamera camera) {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
BATCH.setProjectionMatrix(camera.combined);
BATCH.begin();
renderFbo();
BATCH.end();
}
无需摆弄相机来绘制帧缓冲区内容以覆盖整个屏幕。您可以使用单位投影矩阵和 OpenGL 将默认投影定义为 2 个单位宽和高,以 (0, 0) 为中心的知识。
您不需要结束和开始批处理。在切换渲染表面之前刷新它会更简单一些。
private final Matrix4 originalMatrixTemp = Matrix4();
private static final Matrix4 IDENTITY = Matrix4();
public void renderFbo() {
// Finish drawing anything queued before we switch the frame buffer.
batch.flush();
// Store the current Batch state for things we're going to temporarily change.
originalMatrixTemp.set(BATCH.getProjectionMatrix());
ShaderProgram originalShader = BATCH.getShaderProgram();
int originalBlendSrcFunc = BATCH.getBlendSrcFunc();
int originalBlendDstFunc = BATCH.getBlendDstFunc();
// No need to set up camera projection again.
// It was already set before calling this method.
// This ensures alpha is preserved in case you have overlapping translucent sprites.
BATCH.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE);
// Draw to FBO
frameBuffer.begin();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
for (DrwDat dat: LAYERS.get(layer)) {
dat.draw(BATCH);
}
BATCH.flush();
frameBuffer.end();
/* When you have a custom shader for rendering FBO contents, here's where
you would prepare it.
BATCH.setShader(waterFboShader);
waterFboShader.setUniformf("u_someUniformAttribute", someUniformAttribute);
etc.
*/
// Ensure we're drawing the frame buffer texture without modifying its color.
BATCH.setColor(Color.WHITE);
// Dimensions to the corners of the screen when using an identity matrix for
// projection. Negative height to flip vertically. (OpenGL image space and world
// space have opposite Y directions for some reason.)
BATCH.setProjectionMatrix(IDENTITY);
BATCH.draw(frameBuffer.getColorBufferTexture(), -1, 1, 2, -2);
BATCH.flush();
// Restore state from before this method was called.
BATCH.setShader(originalShader);
BATCH.setProjectionMatrix(originalMatrixTemp);
BATCH.setBlendFunction(originalBlendSrcFunc, originalBlendDstFunc);
}
存储原始矩阵时,您必须将其值复制到您自己的临时实例中,因为 SpriteBatch 会向您传递其自己的最终实例,其值在您应用单位矩阵时将被覆盖。