Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 10 of 13

Thread: Sky box issue

Hybrid View

  1. #1
    Junior Member Newbie
    Join Date
    Jul 2013
    Posts
    12

    Sky box issue

    Hey I've been working on a Skybox for my java game (OpenGL/LWJGL) what my issues is that:

    One the texture is not "stretched" so to say across the quad face (how would I go about that? also the texture is rendered upside down)

    Two I can't get it to translate/rotate properly (the matrix makes it follow the camera which I want. But translate simple moves the skybox away from me, and rotate, well I'm doing something wrong with the pitch,yaw, and roll)

    Notes:
    Camera on load up is facing -Z, -X is left, and +Y is up
    "multipier" can be ignored

    What I need it to do:
    Follow Camera: Check
    Rotate when camera looks around: nope (glRotate works in a sense, saddly works weird cause i'm sure not using params right)
    Texture to be nicely spread across the quad faces: nope

    What am I doing wrong?

    Code :
    package terrain;
     
    import static org.lwjgl.opengl.GL11.GL_RGBA;
     
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Vector;
     
    import loaders.ImageLoader;
     
    import org.lwjgl.opengl.GL11;
    import org.lwjgl.opengl.GL12;
    import org.lwjgl.opengl.GL13;
    import org.lwjgl.opengl.GL14;
    import org.lwjgl.opengl.GL21;
    import org.newdawn.slick.opengl.Texture;
    import org.newdawn.slick.opengl.TextureLoader;
    import org.newdawn.slick.util.ResourceLoader;
     
    import static org.lwjgl.opengl.GL11.*;
     
    import camera.EulerCamera;
     
    public class SkyBox {
     
            private Vector<Texture> textures;
            private EulerCamera cam;
            float boxSize = 5f;
            float texSize = 1f;
            float multipier = 2f;
     
            public SkyBox(EulerCamera cam) 
            {
                    this.cam = cam;
            }
     
            public void draw() {
                	glPushMatrix();               
                    glPushAttrib(GL_ENABLE_BIT);
     
                    glLoadIdentity();                
                    GL13.glActiveTexture(GL13.GL_TEXTURE0);
                    glEnable(GL_TEXTURE_2D);
     
                  //load textures
                    textures = new Vector<Texture>();
                    try 
                    {                   	
                        textures.add(ImageLoader.loadTexture("Sky/front", "PNG"));
                        textures.add(ImageLoader.loadTexture("Sky/left", "PNG"));
                        textures.add(ImageLoader.loadTexture("Sky/back", "PNG"));
                        textures.add(ImageLoader.loadTexture("Sky/right", "PNG"));
                        textures.add(ImageLoader.loadTexture("Sky/top", "PNG"));
                        textures.add(ImageLoader.loadTexture("Sky/bottom", "PNG"));
                    }
                    catch (Exception e)
                    {
                    	System.out.println(e.getStackTrace().toString());
                    	System.out.println(e.getMessage());
                    	System.out.println(e.getCause());
                    	System.out.println(e.getLocalizedMessage());
                    }
     
                    glTranslatef(cam.roll(), cam.pitch(), cam.yaw());
    //                glRotatef(25, cam.roll(), cam.pitch(), cam.yaw());
     
                    // Just in case set all vertices to white.
                glColor4f(1,1,1,1);
     
                // Render the front quad
                textures.get(0).bind();            
                clampToEdge();
                glBegin(GL_QUADS);
                	glTexCoord2f(0, 0); 
                        glVertex3f(  -boxSize * multipier , boxSize * multipier , -boxSize );
                    glTexCoord2f(1, 0); 
                        glVertex3f( boxSize * multipier , boxSize * multipier , -boxSize );
                    glTexCoord2f(1, 1); 
                        glVertex3f( boxSize * multipier,  -boxSize * multipier, -boxSize );
                    glTexCoord2f(0, 1); 
                        glVertex3f(  -boxSize * multipier,  -boxSize * multipier, -boxSize );
                glEnd();
     
                // Render the left quad
                textures.get(1).bind();
                clampToEdge();
                glBegin(GL_QUADS);
                	glTexCoord2f(0, 0); 
                		glVertex3f(  -boxSize , boxSize * multipier, boxSize * multipier);
                	glTexCoord2f(1, 0); 
                		glVertex3f( -boxSize , boxSize * multipier, -boxSize * multipier);
                	glTexCoord2f(1, 1); 
                		glVertex3f( -boxSize ,  -boxSize * multipier, -boxSize * multipier);
                	glTexCoord2f(0, 1); 
                		glVertex3f(  -boxSize ,  -boxSize * multipier, boxSize * multipier);
                glEnd();
     
                // Render the back quad
                textures.get(2).bind();
                clampToEdge();
                glBegin(GL_QUADS);
                	glTexCoord2f(0, 0); 
                		glVertex3f(  boxSize * multipier, boxSize * multipier, boxSize );
                	glTexCoord2f(1, 0); 
                		glVertex3f( -boxSize * multipier, boxSize * multipier, boxSize );
                	glTexCoord2f(1, 1); 
                		glVertex3f( -boxSize * multipier,  -boxSize * multipier, boxSize );
                	glTexCoord2f(0, 1); 
                		glVertex3f(  boxSize * multipier,  -boxSize * multipier, boxSize );
                glEnd();
     
                // Render the right quad
                textures.get(3).bind();
                clampToEdge();
                glBegin(GL_QUADS);
                	glTexCoord2f(0, 0); 
                		glVertex3f(  boxSize , boxSize * multipier, -boxSize * multipier);
                	glTexCoord2f(1, 0); 
                		glVertex3f( boxSize , boxSize * multipier, boxSize * multipier);
                	glTexCoord2f(1, 1); 
                		glVertex3f( boxSize ,  -boxSize * multipier, boxSize * multipier);
                	glTexCoord2f(0, 1); 
                		glVertex3f(  boxSize ,  -boxSize * multipier, -boxSize * multipier);
                glEnd();
     
                // Render the top quad
                textures.get(4).bind();
                clampToEdge();
                glBegin(GL_QUADS);
                	glTexCoord2f(0, 0); 
                		glVertex3f(  -boxSize * multipier, boxSize , boxSize * multipier);
                	glTexCoord2f(1, 0); 
                		glVertex3f( boxSize * multipier, boxSize , boxSize * multipier);
                	glTexCoord2f(1, 1); 
                		glVertex3f( boxSize * multipier,  boxSize , -boxSize * multipier);
                	glTexCoord2f(0, 1); 
                		glVertex3f(  -boxSize * multipier,  boxSize , -boxSize * multipier);
                glEnd();
     
                // Render the bottom quad
                textures.get(5).bind();
                clampToEdge();
                glBegin(GL_QUADS);
                	glTexCoord2f(0, 0); 
                		glVertex3f(  -boxSize * multipier, -boxSize , -boxSize * multipier);
                	glTexCoord2f(1, 0); 
                		glVertex3f( boxSize * multipier, -boxSize , -boxSize * multipier);
                	glTexCoord2f(1, 1); 
                		glVertex3f( boxSize * multipier,  -boxSize , boxSize * multipier);
                	glTexCoord2f(0, 1); 
                		glVertex3f(  -boxSize * multipier,  -boxSize , boxSize * multipier);
                glEnd();
     
                // Restore enable bits and matrix
                glPopAttrib();            
                glPopMatrix();
     
            }
     
            //clamp textures, that edges get don't create a line in between
            private void clampToEdge() {
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            }
    }

  2. #2
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    490
    Quote Originally Posted by Hugo_the_Dwarf View Post
    Hey I've been working on a Skybox for my java game (OpenGL/LWJGL)
    First, a skybox should be a unit cube (i.e. all vertex coordinates should be 1 or -1). The size doesn't matter because it should be drawn first with depth tests and depth writes disabled.

    Second, a skybox shouldn't be translated. The viewpoint should always be at the exact centre of the cube.

    It's hard to say exactly how you should implement the latter because you don't provide the source for the EulerCamera class. But the general idea is to perform the rotation component but not the translation. If you can get a matrix in a suitable form for passing to glLoadMatrix() or glMultMatrix() (i.e. an inverse matrix), then you can just set the translation components (the first three elements in the right-hand column) to zero. Or you may be able to make a copy of the camera then set the copy's position to (0,0,0).

  3. #3
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    The size doesn't matter because it should be drawn first with depth tests and depth writes disabled.
    No, the skybox should be drawn after all opaque objects have been rendered, so that depth tests can cull as much of it out as possible.

  4. #4
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    490
    Quote Originally Posted by Alfonse Reinheart View Post
    No, the skybox should be drawn after all opaque objects have been rendered, so that depth tests can cull as much of it out as possible.
    Then you need to be careful to ensure that the skybox isn't too small (or it will occlude objects) nor too large (or it will get clipped to the far plane).

    OTOH, objects being occluded by the skybox may be preferable to clipping by the far plane, as the skybox rotates with the rest of the scene, so you won't get objects visible at the edges of the screen disappearing when you turn towards them.

    From an efficiency perspective, I'm curious whether early-depth optimisation wins over using the skybox to clear the depth buffer. I suppose that it depends upon how much of the skybox is visible.

  5. #5
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    490
    Quote Originally Posted by Hugo_the_Dwarf View Post
    Rotate when camera looks around: nope (glRotate works in a sense, saddly works weird cause i'm sure not using params right)
    Code :
                    glTranslatef(cam.roll(), cam.pitch(), cam.yaw());
    //                glRotatef(25, cam.roll(), cam.pitch(), cam.yaw());

    Now that I've had a proper look, you probably want something like:
    Code :
                    glRotatef(-cam.roll(),  0, 0, 1);
                    glRotatef(-cam.pitch(), 1, 0, 0);
                    glRotatef(-cam.yaw(),   0, 1, 0);
    although the exact order depends upon how you define these angles with respect to each other.

    Also:
    Quote Originally Posted by Hugo_the_Dwarf View Post
    Camera on load up is facing -Z, -X is left, and +Y is up
    Life will probably be easier in the long run if your world has +X=east, +Y=north, +Z=up. Typically this means a glRotatef(-90, 1, 0, 0) call before everything else.

  6. #6
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    Then you need to be careful to ensure that the skybox isn't too small (or it will occlude objects) nor too large (or it will get clipped to the far plane).
    Or you could just render the skybox with a projection to infinity, thus ensuring that only things clipped by the far plane will clip against the skybox. So nothing clips against it.

    From an efficiency perspective, I'm curious whether early-depth optimisation wins over using the skybox to clear the depth buffer. I suppose that it depends upon how much of the skybox is visible.
    Buffer clears on hardware made in the last decade or so are a function of memory caches. They don't actually modify the memory; when the ROPS go to perform a read/modify/write to a cleared framebuffer, if that cache line hasn't been read since the last clear, it automatically gets the clear value. Same goes for depth testing; if the value hasn't been tested since the last clear, it gets the clear value.

    Clearing the depth buffer is free. Drawing the skybox is not free. Free is better

  7. #7
    Junior Member Newbie
    Join Date
    Jul 2013
    Posts
    12
    Thanks GClements for this code:
    Code :
                 glRotatef(-cam.roll() + 180,  0, 0, -1);
                    glRotatef(-cam.pitch(), 1, 0, 0);
                    glRotatef(-cam.yaw(),   0,-1, 0);
    I've slightly altered it so the would rotate correctly (looking up brings the top into view instead of bottom) so that fixed my rotation issue, but saddly I still don't know how to get that image to stretch all the way across the boxes face.

    Also Thank you Alfonse for the explaination and the link "projection to infinity" I shall read up on this, however this is my first game and I really don't mind too much on how things are rendered at the moment (well I do care, but I just want things to start to work so I can come back later and upgrade it. More or less a learning experience) Once again thank you.

    And thank you too GClements since the rotation code is exactly what I needed, I wasn't sure if I could only use one glRotate call or as many as I wanted (as you pointed out with 3 calls)
    any ideas on the images? Click image for larger version. 

Name:	screencap.jpg 
Views:	82 
Size:	14.2 KB 
ID:	1101

    Edit:
    I managed to flip everything the right way (it was all rotated 180 or rolled in this case) fixed a few other lines of code and it looks like it should... kinda, the image is still just a random spot on the quad.
    Last edited by Hugo_the_Dwarf; 08-05-2013 at 10:27 PM. Reason: Fixed the rotate code

  8. #8
    Junior Member Regular Contributor tksuoran's Avatar
    Join Date
    Mar 2008
    Location
    Cambridge, UK
    Posts
    224
    Quote Originally Posted by Alfonse Reinheart View Post
    Or you could just render the skybox with a projection to infinity, thus ensuring that only things clipped by the far plane will clip against the skybox. So nothing clips against it.
    That would be unnecessarily complicated for a skybox or skydome. To push anything to the far plane, simply use DepthRange(1, 1). Remember to return to normal DepthRange(0, 1) after you have rendered the sky.

  9. #9
    Junior Member Newbie
    Join Date
    Jul 2013
    Posts
    12
    Quote Originally Posted by tksuoran View Post
    That would be unnecessarily complicated for a skybox or skydome. To push anything to the far plane, simply use DepthRange(1, 1). Remember to return to normal DepthRange(0, 1) after you have rendered the sky.
    Tried the glDepthRange calls (starts with 1,1 then another call at the end uses 0,1) and it simply does not draw the skybox at all. Maybe I'm using the calls in the wrong place?

    Anyways anyone have any idea how I messed up the texture placement? because it is dead set on drawing only one tiny image then clamping it to the edges, which is driving me nuts. (I want the clamp to edge else it just tiles the texture, instead of just stretching it as I want.)

  10. #10
    Junior Member Regular Contributor tksuoran's Avatar
    Join Date
    Mar 2008
    Location
    Cambridge, UK
    Posts
    224
    I am just guessing here, but I would suspect the transformation that you use for the sky object is not quite right.

    Try rendering the sky with some simple transformations. First try with identity transform. This should give a "working" but fixed, non-rotating sky. The next step would be to try some rotation only transform.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •