4
votes

In my game I am drawing a scene2d Stage using a custom world coordinate system.

I then want to draw a debug UI with some text like FPS on top of that, but simply using screen coordinates, i.e. where the text is positioned in the upper right corner of the screen. My main render method looks something like this:

@Override
public void render(float delta) {
    Gdx.gl.glClearColor(1, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    gameStage.act(delta);
    gameStage.draw();

    debugInfo.render(delta);
}

The Stage sets a custom viewport:

public GameStage(GameDimensions dimensions, OrthographicCamera camera) {
    // mapWith will be smaller than screen width
    super(new FitViewport(dimensions.mapWidth, dimensions.mapHeight, camera));
    ...
}

The DebugInfo render code looks like this:

public DebugInfo() {
    Matrix4 mat = new Matrix4();
    mat.setToOrtho2D(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    batch.setProjectionMatrix(mat);
}

@Override
public void render(float delta) {
    batch.begin();
    font.setScale(2f);
    drawText("FPS " + Gdx.graphics.getFramesPerSecond());
    batch.end();
}

private void drawText(String text) {
    final BitmapFont.TextBounds textBounds = font.getBounds(text);
    textPos.x = Gdx.graphics.getWidth() - textBounds.width - MARGIN;
    textPos.y = Gdx.graphics.getHeight() - MARGIN;
    textPos.z = 0;
    font.draw(batch, text, textPos.x, textPos.y);
}

The problem is that even though I make no reference whatsoever to the stage's world system or its camera, but strictly use pixel values and an according projection matrix, the text appears in the upper right corner of the stage's viewport, which is smaller than the screen. I want it to appear detached from the stage in the screen's corner instead.

I could pinpoint the problem down to the creation of the Stage instance itself; stopping to draw it is not enough. I actually have to remove the call to super(new FitViewport(...)) to prevent this from happening.

This leads me to believe that I need to somehow reset the viewport of the rendering pipeline before I render the UI overlay? How would I do that?

1
Actually I just noticed the whole setOrtho2D stuff and the custom matrix isn't even required. It's simply the Stage taking over everything and screwing up subsequent renderings. As soon as I remove it everything works as expected...Matthias
Okay, by trial and error, I figured I can fix the problem by using an ExtendViewport instead of FitViewport. I would still like to better understand what's happening and why simply creating a Stage instance affects the entire rendering pipeline?Matthias

1 Answers

2
votes

My first answer was wrong. Now, when I've looked into Viewport source code I can see that it uses OpenGL's glViewPort and indeed it affects all subsequent draw calls. So you have to call glViewport with appropriate dimensions before rendering your stuff:

@Override
public void render(float delta) {
    Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    batch.begin();
    font.setScale(2f);
    drawText("FPS " + Gdx.graphics.getFramesPerSecond());
    batch.end();
}