PDA

View Full Version : Improving Skybox



Mukund
06-03-2011, 03:52 PM
Hello Everyone,

i have built this skybox using the following code:



static GLuint texName[6];

void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

for (int i = 0; i < 6/* Skybox */; i++) {
readBMP(texFileNames[fileNo++], checkImageWidth, checkImageHeight); // reading from BMP files

glGenTextures(1, texName + i);
glBindTexture(GL_TEXTURE_2D, texName[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth,
checkImageHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, texelDataBMP);
}
}


void keyBoard(unsigned char a, int x, int y)
{

if (a == 'a')
rotAng += 10;

glutPostRedisplay();
}

void drawTexturedFace()
{
glBindTexture(GL_TEXTURE_2D, texName[texFlag++]);

glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -2.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-2.0, 2.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(2.0, 2.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(2.0, -2.0, 0.0);
glEnd();
}

void display(void)
{

glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 1,
0, 0, 0,
0, 1, 0);
glRotatef(rotAng, 0, 1, 0);

// Front face
glPushMatrix();
glTranslatef(0, 0, -2);
drawTexturedFace();
glPopMatrix();

// Top Face
glPushMatrix();
glTranslatef(0, 2, 0);
glRotatef(90, 1, 0, 0);
drawTexturedFace();
glPopMatrix();

// Bottom Face
glPushMatrix();
glTranslatef(0, -2, 0);
glRotatef(-90, 1, 0, 0);
drawTexturedFace();
glPopMatrix();

// Left Face
glPushMatrix();
glTranslatef(-2, 0, 0);
glRotatef(90, 0, 1, 0);
drawTexturedFace();
glPopMatrix();

// Right Face
glPushMatrix();
glTranslatef(2, 0, 0);
glRotatef(90, 0, -1, 0);
drawTexturedFace();
glPopMatrix();

// Back Face
glPushMatrix();
glTranslatef(0, 0, 2);
glRotatef(180, 0, 1, 0);
drawTexturedFace();
glPopMatrix();

glutSwapBuffers();

}

Now, is there any way i can optimize it further(other than using VBOs)
Is there any way i could improve, say drawTexturedFace()?

PS: init() is called just once, initially when the program starts.

Any suggestions would be helpful.
Thanks in advance.

Alfonse Reinheart
06-03-2011, 04:00 PM
Are you having performance problems with it? If not, what do you need to optimize it for?

Anyway, if you really want to do so, draw an actual cube instead of 6 faces. Use a cubemap instead of 6 textures.

Mukund
06-03-2011, 04:10 PM
Are you having performance problems with it? If not, what do you need to optimize it for?

Well not really. i am just experimenting around with textures. i have a GPU on my machine, so i don't notice any performance issues. However to ensure it runs well on all machines, i would like to optimize it as far as possible.

Dan Bartlett
06-03-2011, 05:34 PM
Drawing the skybox after the rest of your opaque objects (but before transparent objects) can provide a speed-up - especially if dealing with situations where not much of the skybox is visible such as when inside or looking down at ground, but can be a bit more difficult to do. See http://www.opengl.org/wiki/Skybox and http://www.opengl.org/wiki/Early_Z

I'm not sure how much expensive clearing the color buffer is, but it's not really needed if you going to be drawing to every pixel with opaque objects anyway - you should always clear the depth buffer though.

Rather than messing with the modelview matrix for each face, it would probably be easier if you had all the vertices for the sky in a common co-ordinate system, eg.
positions = {{-0.5, -0.5, -0.5}, {0.5, -0.5, -0.5}, {0.5, 0.5, -0.5}, {-0.5, 0.5, -0.5}, ... }
texcoords = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, ...}

And then just drew these using vertex arrays http://www.songho.ca/opengl/gl_vertexarray.html or vertex arrays in GPU side VBOs http://www.songho.ca/opengl/gl_vbo.html
Once you have it rendering a basic model for the sky, you could always switch it to a more complex model at a later stage with no changes to OpenGL code, just to the model.

Whatever method you choose for drawing these few triangles (immediate mode/vertex arrays/VBOs) is likely to result in a no measurable difference in framerate, since it'll be fairly irrelevant compared to the time spent by OpenGL actually drawing the pixels.

mhagain
06-03-2011, 06:36 PM
VBOs aren't going to give you any gain with this. The vertex count is so low that there is nothing measurable to be had, and if you need to switch VBOs in order to draw it you'll likely run slower.

Where you can get gain is by determining which face(s) is/are behind the view position and not bothering to send them to the GPU. But it's going to be extremely marginal, as the GPU is going to reject these faces quite early in the pipeline anyway, and the vertex count is so low that you're never going to be bottlenecking on that.

Yeah, drawing the box after all other geometry will be more efficient, but it depends on how fillrate-bound you are. If you've already got something like 20x overdraw (pulling a number out of a hat here) then going to 21x is peanuts in the bigger scheme of things.

So the only really worthwhile optimization would be using a cubemap instead of 6 individual textures, and batching your quads. But it's all going to be very marginal and factors like how much overdraw you currently have, and whether or not you're fillrate-bound, are entirely program-dependent. No silver bullet.

Mukund
06-04-2011, 09:43 AM
Thanks for the replies mhagain and Dan Bartlett. Are there any tips you would like to give while using textures in general?

What i mean to say is, now sending a lot of polygons for rendering slows down things. Similarly, using textures, is it possible that things might go slow?

Say for eg:
Using large images for texturing(in fact i'm using 1024x124 image for texturing right now). That would slow things down a little right?

or say the filtering method used.

So, are there any such things i need to keep in mind when i deal with a lot of texturing?

mhagain
06-04-2011, 12:37 PM
A large texture will always be slower than a smaller one, yeah, but to be honest I think you're talking micro-optimizations right now. Things like texture sizes and filtering modes can be adjusted afterwards if you need to, but you should wait until you've definitely determined that they're a bottleneck, and bear in mind that the other side of this tradeoff is a loss in quality (which may be unacceptable - it depends on your program's requirements).

Any hardware from the past 10 or so years should be able to handle a 1024x1024 texture with ease. The most important thing is to get as many primitives as possible between each set of state changes and that involves sorting your opaque geometry by state. You'll never get perfect - all programs have a bottleneck somewhere - so you just need to aim for it being fast enough.

RefleX
06-04-2011, 12:54 PM
This will remove the seams if you are having any.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

One way of drawing your skybox is to render it before anything else at the location of your camera and disable depth testing. You will have an infinite skybox and what ever gets drawn next will always be rendered in front of the skybox since the skybox does not record depth.

Mukund
06-04-2011, 12:59 PM
Thanks mhagain and RefleX.

mhagain
06-04-2011, 02:15 PM
Another way is to draw it as a 10x10x10 cube and set glDepthRange (1, 1) - you'll need to draw it after other geometry for that, but it will also give you an infinite skybox and you won't need to adjust your far clipping plane or tweak your skybox size.