PDA

View Full Version : Cubemapped skybox problem



dpoon
05-27-2004, 03:15 AM
Hi,

I am rendering a skybox using a cubemap. Since the positive and negative y faces are oriented strangely (i.e., mirrored and flipped) compared to the other x and z faces, my rendering code manipulates the glTexCoord3f() calls to fix this. The skybox renders correctly on my WinXP box with a 9700Pro (cat 4.5 drivers). However I notice intermittent white dots appearing along some of the seams between cube faces. Since I am already using GL_CLAMP_TO_EDGE for the cubemap I am a bit puzzled as to why this is happening. I tested it on another WinXP box with a Geforce2 (old det 43 driver) and the white dots were not as noticeable -- but they were still present. Since this problem is appearing on both machines I'm pretty sure that I've screwed up my code somewhere :D

Here's the code I use to render my skybox. I've already bound the cubemap elsewhere to texture unit zero.



GLvoid RenderSkybox(GLfloat width, GLfloat height, GLfloat depth)
{
GLfloat dx = width * 0.5f;
GLfloat dy = height * 0.5f;
GLfloat dz = depth * 0.5f;

glPushAttrib(GL_FOG_BIT | GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT);
glDisable(GL_FOG);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);

glBegin(GL_QUADS);

// Front (negative Z) face.
glTexCoord3f( dx, -dy, -dz); glVertex3f(-dx, -dy, -dz);
glTexCoord3f(-dx, -dy, -dz); glVertex3f( dx, -dy, -dz);
glTexCoord3f(-dx, dy, -dz); glVertex3f( dx, dy, -dz);
glTexCoord3f( dx, dy, -dz); glVertex3f(-dx, dy, -dz);

// Back (positive Z) face.
glTexCoord3f(-dx, -dy, dz); glVertex3f( dx, -dy, dz);
glTexCoord3f( dx, -dy, dz); glVertex3f(-dx, -dy, dz);
glTexCoord3f( dx, dy, dz); glVertex3f(-dx, dy, dz);
glTexCoord3f(-dx, dy, dz); glVertex3f( dx, dy, dz);

// Bottom (negative Y) face.
glTexCoord3f( dx, -dy, -dz); glVertex3f(-dx, -dy, dz);
glTexCoord3f(-dx, -dy, -dz); glVertex3f( dx, -dy, dz);
glTexCoord3f(-dx, -dy, dz); glVertex3f( dx, -dy, -dz);
glTexCoord3f( dx, -dy, dz); glVertex3f(-dx, -dy, -dz);

// Top (positive Y) face.
glTexCoord3f( dx, dy, dz); glVertex3f(-dx, dy, -dz);
glTexCoord3f(-dx, dy, dz); glVertex3f( dx, dy, -dz);
glTexCoord3f(-dx, dy, -dz); glVertex3f( dx, dy, dz);
glTexCoord3f( dx, dy, -dz); glVertex3f(-dx, dy, dz);

// Left (negative X) face.
glTexCoord3f( dx, -dy, dz); glVertex3f( dx, -dy, -dz);
glTexCoord3f( dx, -dy, -dz); glVertex3f( dx, -dy, dz);
glTexCoord3f( dx, dy, -dz); glVertex3f( dx, dy, dz);
glTexCoord3f( dx, dy, dz); glVertex3f( dx, dy, -dz);

// Right (positive X) face.
glTexCoord3f(-dx, -dy, -dz); glVertex3f(-dx, -dy, dz);
glTexCoord3f(-dx, -dy, dz); glVertex3f(-dx, -dy, -dz);
glTexCoord3f(-dx, dy, dz); glVertex3f(-dx, dy, -dz);
glTexCoord3f(-dx, dy, -dz); glVertex3f(-dx, dy, dz);

glEnd();
glPopAttrib();
}Any ideas?

Jared
05-27-2004, 04:25 AM
Originally posted by dpoon:
Any ideas?ill start with a question:
youre using cubemapping, so why on earth would you even bother to render a box? either draw 6 quads with 2d textures or one quad with cubemapping. but i dont see the point in doing both which seems to be nothing but pointless extra work per face.


glEnable(GL_TEXTURE_CUBE_MAP_ARB);
/*no need to clear color buffer if we draw all over it (yes, unlike clearing the depth buffer this does make a difference on my machine.. in fact, drawing the quad and clearing the color buffer seem to take pretty much the same time)*/
glDisable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, SkyCube);

Vector3 vec(Camera.Forward), v;
Vector3 up(Camera.Up);
//yFac = half the frustum height at z=1
up*=Camera.yFac;
Vector3 right(Camera.Right);
//same for width.. point is to have a screen sized quad
right*=Camera.xFac;

glBegin(GL_QUADS);
/*confused? Vector3 has a float* cast operation so it can be used with all the x3fv functions*/
glTexCoord3fv(v=vec-right+up);
glVertex3fv(v+Camera.Position);
glTexCoord3fv(v=vec-right-up);
glVertex3fv(v+Camera.Position);
glTexCoord3fv(v=vec+right-up);
glVertex3fv(v+Camera.Position);
glTexCoord3fv(v=vec+right+up);
glVertex3fv(v+Camera.Position);
glEnd();

glEnable(GL_DEPTH_TEST);guessing from your code you should be fine if you
a) forget drawing anything but the front face
b) set the modelview to identity
c) multiply <dx,dy,dz> with the cameras transformation matrix (minus translation) for texture coords.
or as alternative:
multiply the texture matrix with the cameras matrix minus the translation

so a cleaned up version would be

glEnable(GL_TEXTURE_CUBE_MAP_ARB);
glDisable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, SkyCube);

glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(Camera.Right);

glBegin(GL_QUADS);
/*4d texcoords to force w=0, so we dont need to remove the translation part from the cam matrix*/
glTexCoord4f(-Camera.xFac, Camera.yFac, 1, 0);
glVertex3f(-Camera.xFac, Camera.yFac, 1);
glTexCoord4f(-Camera.xFac, -Camera.yFac, 1, 0);
glVertex3f(-Camera.xFac, -Camera.yFac, 1);
glTexCoord4f(Camera.xFac, -Camera.yFac, 1, 0);
glVertex3f(Camera.xFac, -Camera.yFac, 1);
glTexCoord4f(Camera.xFac, Camera.yFac, 1, 0);
glVertex3f(Camera.xFac, Camera.yFac, 1);
glEnd();

glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_DEPTH_TEST);

Humus
05-27-2004, 07:21 PM
Also, ensure that you have set GL_CLAMP_TO_EDGE_EXT for s and t.