LIBGDX Framebuffer отображается как черный ящик - PullRequest
0 голосов
/ 18 июня 2020

Мы разобрались с проблемой. Я избавлялся от фреймбуфера перед его использованием.

Недавно я спросил, как правильно использовать Libgdx Framebuffer .

Подводя итог, я делаю плитку на основе игры, и я хотел понять, как настроить и использовать объект фреймбуфера, чтобы в конечном итоге начать экспериментировать с шейдерами. Я хотел исключить «водяные плитки» из обычного цикла рисования и вместо этого визуализировать их во фреймбуфере. Затем отобразите буфер кадра на экране.

(я не использую классы «Scene2d» или «Tiled»)

Ссылка на предыдущий вопрос: Как правильно использовать LIBGDX FrameBuffer .

Несмотря на то, что ответ, который я принял, не работал в моей конкретной программе, он действительно работал, когда я опробовал его на меньшей, более ограниченной программе (показано ниже).

Это работает :

public void render() {
    float dt = Gdx.graphics.getDeltaTime();
    Cam.instance.getCamera().translate(direction.x*speed*dt, direction.y*speed*dt,0);
    Cam.instance.update();

    // clear the screen, set batch's projection matrix
    Gdx.gl.glClearColor(0, 0, 0, 0);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    batch.setProjectionMatrix(Cam.instance.getCamera().combined);

    // draw texture as layer 0
    batch.begin();
    batch.draw(green,606,306);

    batch.flush(); // No need to call batch.end() / batch.begin()

    // Storing the original values of the batch before changing it.
    originalMatrixTemp.set(batch.getProjectionMatrix());
    int originalBlendSrcFunc = batch.getBlendSrcFunc();
    int originalBlendDstFunc = batch.getBlendDstFunc();

    // Sorcery as far as i am concerned. "Ensures alpha is preserved in case of overlapping translucent sprites"
    batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE);


    frameBuffer.begin(); // initialize framebuffer
    // clear the colors of the batch
    Gdx.gl.glClearColor(0, 0, 0, 0);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    batch.draw(red,256,0); // Draw another texture, now unto the framebuffer texture
    batch.flush(); // flush batch
    frameBuffer.end(); // end framebuffer

    // "Ensure we're drawing the frame buffer texture without modifying its color"
    batch.setColor(Color.WHITE);
    
    // I think we are setting the projection to "default" (-1,1,2,-2)
    batch.setProjectionMatrix(IDENTITY);
    
    // draw the framebuffers texture across all the screen (layer 1)
    batch.draw(frameBuffer.getColorBufferTexture(),-1, 1, 2, -2);
    batch.flush();
    
    // restoring the original state
    batch.setProjectionMatrix(originalMatrixTemp);
    batch.setBlendFunction(originalBlendSrcFunc, originalBlendDstFunc);

    // drawing arbitrary layer 2
    batch.draw(green,300,300);

    batch.end(); // end of cycle
}

и показывает (красный квадрат - текстура фреймбуфера): Arbitrary squares

The cycle is: Begin -> Draw something -> Draw, using buffer -> Draw something -> end.

So my question is then, why does this not work:

private void renderFbo(int layer) {
    batch.flush();

    originalMatrixTemp.set(batch.getProjectionMatrix());
    int originalBlendSrcFunc = batch.getBlendSrcFunc();
    int originalBlendDstFunc = batch.getBlendDstFunc();

    batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE);

    fbo.begin();
    Gdx.gl.glClearColor(0, 0, 0, 0);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    // Drawing the layer unto the framebuffer:
    for (DrwDat dat: layers.get(layer)) { dat.draw(batch); }

    batch.flush();
    fbo.end();

    batch.setColor(Color.WHITE);
    batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
    batch.setProjectionMatrix(IDENTITY);

    // Halving the output texture to see the issue clearer. whole screen: (-1, 1, 2, -2)
    batch.draw(fbo.getColorBufferTexture(), -0.5f, 0.5f, 1f, -1f);
    batch.flush();

    batch.setProjectionMatrix(originalMatrixTemp);
    batch.setBlendFunction(originalBlendSrcFunc, originalBlendDstFunc);
}

With this being the immediate context:

public void draw() {

    Gdx.gl.glClearColor(1, 1, 1, 1); // clearing with WHITE to see the framebuffer texture
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    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)) { dat.draw(batch);}
            if (i==1) { renderFbo(i); } // calling the framebuffer-using method for "water layer"
            else{
                for (DrwDat dat: layers.get(i)) {
                    dat.draw(batch);
                }
            }
        }
    }

Instance variables in the "draw class" :

public class DrwHandler {

private static final String TAG = DrwHandler.class.getName();
public static DrwHandler instance = new DrwHandler();
private final Matrix4 originalMatrixTemp = new Matrix4();
private static final Matrix4 IDENTITY = new Matrix4();
private Map> layers;
private OrthographicCamera camera;
private FrameBuffer fbo;
private SpriteBatch batch;

private static final int NUM_LAYERS = 8;
private static final boolean[] RENDER = new boolean[NUM_LAYERS];
private static final boolean[] SORT = new boolean[NUM_LAYERS];

private DrwHandler() {
    fbo = new FrameBuffer(Pixmap.Format.RGBA8888, Settings.SCREEN_W,Settings.SCREEN_H,false);
    batch = new SpriteBatch();
    layers = new HashMap<>();
    layers.put(0,new ArrayList<>());
    layers.put(1,new ArrayList<>());
    layers.put(2,new ArrayList<>());
    layers.put(3,new ArrayList<>());
    layers.put(4,new ArrayList<>());
    layers.put(5,new ArrayList<>());
    layers.put(6,new ArrayList<>());
    layers.put(7,new ArrayList<>());
}

It shows: black box

The "black box" is the framebuffer texture (redused in size). The white background is the clear color. and the green is a foreground layer.

It is black regardless of changing the Gdx.gl.glClearColor(0, 0, 0, 0) within the context of the framebuffer rendering to some other color.

without the renderFbo() method, it renders normally like this:

Without Buffer

Now i have heard Static references can cause issues with OpenGL-related objects:

"If you will be building for Android, never use static references to any OpenGL-related objects unless you have an expert understanding of the LibGDX lifecycle. Even then, it is an error-prone practice. People come on here to ask about black textures pretty frequently and 99% of the time it has to do with some static reference being used incorrectly."

I am not building for android. And since my previous question i have removed static objects. just to be sure.

But i do use statics in a few select classes like this (example):

public class Cam {

public static Cam instance = new Cam();
private OrthographicCamera camera;

private Cam() {
    camera = new OrthographicCamera(Settings.SCREEN_W, Settings.SCREEN_H);
}

(including my Assets class and Draw class):

Trying to think about what else.. I guess we will try with this first. Se if something sticks out to you. Really could need some help right about now. Been banging my head against the wall for a while. Thank you.

Here is a link to some source files that could be relevant:

Источник

...