cant get a 2D Camera in LWJGL working (beginner)

Started by MonsieurBlutbad, July 18, 2013, 15:11:53

Previous topic - Next topic

MonsieurBlutbad

Hi all,

I am working on a 2D Game and I try to set up a simple camera for it (just moving and zooming).
Unfortunatly, I don't get it working at all.
Since I am new to LWJGL and OpenGL in general I have no idea, if I am missing out on something very basic
or if the problem is more complex.

With my googling I found out that there are 3 approaches:
1.) Use glScalef and glTranslatef (this seems to be very easy... in theoriy...)
2.) Use gluLookAt and gluPerspective (this seems to be more sophisticated, but maybe too much for a 2D Game?)
3.) Hardcode the "camera" position and zoom level into each draw call (now that seems to be a terrible way to go, even though I am sure I could do that...)

The most effort so far I put into the glScalef and glTranslatef approach.
My code is compiling, but neither the scaling nor the translating has any
effect on the screen.

Maybe somebody can take a look at my code and help me out

So here is my code:
// called once at start
protected void create() {
      // Enable blending
      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   // enable textures since we're going to use these for our sprites
      glEnable(GL_TEXTURE_2D);
       
      // disable the OpenGL depth test since we're rendering 2D graphics
      glDisable(GL_DEPTH_TEST);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
       
      glOrtho(0, WIDTH, HEIGHT, 0, -1, 1);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glViewport(0, 0, WIDTH, HEIGHT);
      // Set clear to transparent black
      glClearColor(0f, 0f, 0f, 0f);
}

// called every frame
protected void render(){
    // Clear the screen
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    float centerX = WIDTH * 0.5f;
    float centerY = HEIGHT * 0.5f;
    //Move to center of scene
    glTranslatef(centerX,centerY,0);   
    //Scale at center
    glScalef(2,2,1);          
    //Move back to origin
    glTranslatef(-centerX,-centerY,0); 
    glPushMatrix();
      // ... render our game here ...
      spriteBatch.begin();
                         // next line is Pseudo-Code, but this is the way i draw all my graphics. 
                         // I pass the spriteBatch to all my Entities, and they are drawn in the fashion shown below
               spriteBatch.draw( textureRegion, x, y, width, height );
      spriteBatch.end();
     glPopMatrix();
}



The SpriteBatch I use is not by me.
I use this one here: https://github.com/mattdesl/lwjgl-basics/blob/master/src/mdesl/graphics/SpriteBatch.java
Might it be the source of my problem? I tried to wrap my head around what actually is happening in that SpriteBatch,
but it is way beyond me

quew8

EDIT: I just see that the libraries owner gave you a far more succinct answer over on JGO. Link is here if anyone else should wonder this way: http://www.java-gaming.org/topics/cant-get-a-2d-camera-in-lwjgl-working-beginner/30178/view.html



You're quite right, the problem is that the SpriteBatcher uses custom shaders. The default shader it provides uses its own transformation matrix variable. Taking a look at the source code, I believe it intends for you to upload the matrix yourself, for which it provides the name of the variable as a static final String called U_PROJ_VIEW.

What this means is that you will have to make the transformation matrix yourself rather than using glTranslate, glScale etc. You will have to combine the projection and modelview matrices into one as well. I will put a link at the end for what I think is a good place to learn about this. Once you have the desired matrix as a Matrix4f (org.lwjgl.util.vector I think) do this.

spriteBatch.getShader().setUniformMatrix(SprteBatch.U_PROJ_VIEW, false, transformMatrix);


Please note that I have never used this library before and although this way should work it seems very odd to me having eyed up the rest of that code - I would not be surprised if there is an easier way. To this end I believe @mattdesl has written extensive tutorials to accompany his library. I don't know where to find them but I'm sure it isn't that hard to find or you could pm him. Check out the tutorials before you attempt my solution.

Here is the link for some matrix maths stuff (and other necessary stuff - do not skip anything): http://www.wildbunny.co.uk/blog/vector-maths-a-primer-for-games-programmers/

Also I understand that this is a rather large step forward - please continue asking questions.

MonsieurBlutbad

Thank you for your kind answer! The site you linked me with the matrix stuff is really good. I was able to follow along for quite some time :D
As you allready saw, davedes, the creator of the spritebatch I use, gave me some great hints at JGO. He also provided me with a code how to use translation, scale and rotation with his spriteBatch, that's working like a charm. If anyone has a similar problem you should definetly check it out.
Here is the probably most important excerpt
//get the instance of the view matrix for our batch
      Matrix4f view = batch.getViewMatrix();
      
      //reset the matrix to identity, i.e. "no camera transform"
      view.setIdentity();
      
      //scale the view
      if (zoom != 1f) {
         view.scale(new Vector3f(zoom, zoom, 1f));
      }
      
      //pan the camera by translating the view matrix
      view.translate(new Vector2f(panX, panY));
      
      //after translation, we can rotate...
      if (rot!=0f) {
         //we want to rotate by a center origin point, so first we translate
         view.translate(new Vector2f(Display.getWidth()/2, Display.getHeight()/2));
         
         //then we rotate
         view.rotate(rot, new Vector3f(0, 0, 1));
         
         //then we translate back
         view.translate(new Vector2f(-Display.getWidth()/2, -Display.getHeight()/2));
      }
      
      //apply other transformations here...
      
      
      //update the new view matrix
      batch.updateUniforms();
      
      //start the sprite batch
      batch.begin();
...
      batch.end();