2
\$\begingroup\$
import com.badlogic.gdx.Game;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class MyGame extends Game {
    public OrthographicCamera camera;
    public SpriteBatch        batch;
    //..

    @Override
    public void create() {
        //..
        batch = new SpriteBatch();

        Gdx.gl.glClearColor(0, 0, 0, 1);
        batch.setProjectionMatrix(camera.combined);
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        //..
    }

In LibGDX Doc
Gdx.gl.glClearColor(0, 0, 0, 1); and batch.setProjectionMatrix(camera.combined);
is setting in render() method at a time.
I use this definitions in create() method at once, and it is running perfect.

So why should i use this definitions in render() method? is't it a performance loss?

\$\endgroup\$
1
  • \$\begingroup\$ RE: "is't it a performance loss?", have you actually measured a performance loss? Or is that just a theorycrafting question? \$\endgroup\$ – Trevor Powell Apr 14 '15 at 3:10
1
\$\begingroup\$

Setting the glClearColor, as Josh Petrie said, is only necessary to do every frame if you do not know if another part of your program is changing it. Although, usually you would be drawing your own background, which would cover the entire background, so the color should not matter. (Of course, you still need to clear the screen every frame to prevent possible ghosting, but you understand that)

As for setting the projection matrix, it is important that you call this every frame, if you have a moving camera. If you never need to call camera.update(), which is done after you change one of the camera's attributes, then you also need to update the batch's projection matrix. This is because the batch, or as I would assume for your case, specifically the SpriteBatch does not directly use the camera's projection matrix, instead it sets its own projection matrix to the same values as the camera's matrix, like so:

//within SpriteBatch
@Override
public void setProjectionMatrix (Matrix4 projection) {
    if (drawing) flush();
    projectionMatrix.set(projection); <-- this line
    if (drawing) setupMatrices();
}

And the camera's projection matrix, or in your case, the combined matrix, is changed in every camera.update() call:

//this is in OrthographicCamera
@Override
public void update (boolean updateFrustum) {
    projection.setToOrtho(zoom * -viewportWidth / 2, zoom * (viewportWidth / 2), zoom * -(viewportHeight / 2), zoom
        * viewportHeight / 2, near, far); <-- this line
    view.setToLookAt(position, tmp.set(position).add(direction), up);
    combined.set(projection); <-- this line
    Matrix4.mul(combined.val, view.val); <-- and this line

    if (updateFrustum) {
        invProjectionView.set(combined);
        Matrix4.inv(invProjectionView.val);
        frustum.update(invProjectionView);
    }
}

So, unless your not ever moving your camera or changing any of its attributes, then it is safer for you to set the projection matrix every frame.

For example, the Scene2D's Stage resets it every frame:

public void draw () {
    Camera camera = viewport.getCamera();
    camera.update(); <-- updates the camera

    if (!root.isVisible()) return;

    Batch batch = this.batch;
    if (batch != null) {
        batch.setProjectionMatrix(camera.combined); <-- resets the matrix
        batch.begin();
        root.draw(batch, 1);
        batch.end();
    }

    if (debug) drawDebug();
}
\$\endgroup\$
2
\$\begingroup\$

In LibGDX Doc Gdx.gl.glClearColor(0, 0, 0, 1); and batch.setProjectionMatrix(camera.combined); is setting in render() method at a time. I use this definitions in create() method at once, and it is running perfect.

So why should i use this definitions in render() method? is't it a performance loss?

The clear color is part of your OpenGL context state and, once set, will not be changed or reset unless you (or some code you call) does so. Consequently, you need only call glClearColor once during initialization if you know you (and all code you call) will never again change it.

You can call it per-frame if you like, especially if your code calls out to external code you aren't in control over and whose actions cannot be determined when you write your own code (such as plugins). But you don't need to. Generally the "performance impact" of doing so will be non-measurable.

The same is true of setting the state for the projection matrix; you only need to do it once, unless you need to change it or restore it after some other code has potentially changed it.

That sample code is just that: sample code. It's design to clearly and concisely illustrate a point.

\$\endgroup\$
0
\$\begingroup\$

Edit: As usual, I've not paid attention and answered a GL question with DirectX code; sorry... Although the API differs, the idea is very much the same.

It will technically qualify as a performance loss, but it may be unavoidable. Ideally, you only want to notify the video card of changes to "whatever is current". Since you are in complete control of the process, you can reliably predict the "current state" throughout a render.

This code demonstrates two cases:

//Current topology doesn't matter
if (someBool)
{
    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
    ...
    context->GSSetShader(...); //Activate geometry shader
    context->Draw(...);
    context->GSSetShader(NULL); //De-activate geometry shader here
}
//context->GSSetShader(NULL); //Not here; it *might* not be active
//Current topology *might* be POINTLIST
//Have to set it every time and eat the performance hit
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);

this adheres to reporting only changes more strictly, but the performance gain may not be noticable:

//If we **know** that the current topology will be POINTLIST, we can even omit the else
if (someBool)
{
    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
    ...
    context->GSSetShader(...); //Activate geometry shader
    context->Draw(...);
    //Undo everything done
    context->GSSetShader(NULL); //De-activate geometry shader here
    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
}
else context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
//Current topology is now POINTLIST regardless

another:

if (cameraMatrixDirty) //Don't "set" it, if it's already set
{
   batch.setProjectionMatrix(camera.combined)
   cameraMatrixDirty = false;
}

In the worst case, you have added an if() that evaluates to false every frame.
In the best case, you have saved XX redundant state calls.

Drawing A,B,C because that's how it makes the most sense to you is fine, to get the basic code written. In the end, you're asking the GPU to draw it, not yourself, so it needs to make the best sense to it. Drawing C,A,B, instead of A,B,C, may save you many state changes and produce identical on-screen results.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.