PDA

View Full Version : Skybox



Quaver
07-27-2013, 04:05 PM
I drew a standard textured cube like so:


glBindTexture(GL_TEXTURE_2D, top);
glBegin(GL_QUADS);
//glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2d(1.0f, 0.0f); glVertex3f( width, height, -length); // Top Right Of The Quad (Top)
glTexCoord2d(1.0f, 1.0f); glVertex3f(-width, height, -length); // Top Left Of The Quad (Top)
glTexCoord2d(0.0, 1.0f); glVertex3f(-width, height, length); // Bottom Left Of The Quad (Top)
glTexCoord2d(0.0, 0.0f); glVertex3f( width, height, length); // Bottom Right Of The Quad (Top)
glEnd();

glBindTexture(GL_TEXTURE_2D, front);
glBegin(GL_QUADS);
//glNormal3f(0.0f, 0.0f, -1.0f);
glTexCoord2d(0.0f, 0.0f); glVertex3f( width, height, length); // Top Right Of The Quad (Front)
glTexCoord2d(1.0f, 0.0f); glVertex3f(-width, height, length); // Top Left Of The Quad (Front)
glTexCoord2d(1.0f, 1.0f); glVertex3f(-width, -height, length); // Bottom Left Of The Quad (Front)
glTexCoord2d(0.0f, 1.0f); glVertex3f( width, -height, length); // Bottom Right Of The Quad (Front)
glEnd();

glBindTexture(GL_TEXTURE_2D, back);
glBegin(GL_QUADS);
//glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2d(0.0f, 1.0f); glVertex3f( width, -height, -length); // Bottom Left Of The Quad (Back)
glTexCoord2d(1.0f, 1.0f); glVertex3f(-width, -height, -length); // Bottom Right Of The Quad (Back)
glTexCoord2d(1.0f, 0.0f); glVertex3f(-width, height, -length); // Top Right Of The Quad (Back)
glTexCoord2d(0.0f, 0.0f); glVertex3f( width, height, -length); // Top Left Of The Quad (Back)
glEnd();

glBindTexture(GL_TEXTURE_2D, left);
glBegin(GL_QUADS);
//glNormal3f(-1.0f, 0.0f, 0.0f);
glTexCoord2d(1.0f, 0.0f); glVertex3f(-width, height, -length); // Top Right Of The Quad (Left)
glTexCoord2d(1.0f, 1.0f); glVertex3f(-width, -height, -length); // Top Left Of The Quad (Left)
glTexCoord2d(0.0f, 1.0f); glVertex3f(-width, -height, length); // Bottom Left Of The Quad (Left)
glTexCoord2d(0.0f, 0.0f); glVertex3f(-width, height, length); // Bottom Right Of The Quad (Left)
glEnd();

glBindTexture(GL_TEXTURE_2D, right);
glBegin(GL_QUADS);
//glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2d(0.0f, 0.0f); glVertex3f( width, height, -length); // Top Right Of The Quad (Right)
glTexCoord2d(1.0f, 0.0f); glVertex3f( width, height, length); // Top Left Of The Quad (Right)
glTexCoord2d(1.0f, 1.0f); glVertex3f( width, -height, length); // Bottom Left Of The Quad (Right)
glTexCoord2d(0.0f, 1.0f); glVertex3f( width, -height, -length); // Bottom Right Of The Quad (Right)
glEnd();

And it works... But it just clearly looks like a cube:

http://s22.postimg.org/dtj4bzkld/screen.png

What am I missing?

Ed Daenar
07-27-2013, 04:16 PM
You are missing correct textures for a sky box. You need textures that are seamless with the corresponding adjacent cube faces or else you'll obviously see a difference between the faces.

GClements
07-27-2013, 05:34 PM
What am I missing?


You are missing correct textures for a sky box. You need textures that are seamless with the corresponding adjacent cube faces or else you'll obviously see a difference between the faces.

It's not just a case of textures being seamless, they need to be the result of projecting a panorama onto the faces of a cube. If you're using photographs, you can't just paste them together; you have to re-project them correctly.

Also: a skybox doesn't move; it's always centred on the viewpoint. If that grass is the bottom face of the skybox, you'd better not be planning on moving the viewpoint.

And you want to avoid the horizon being visible. You typically ensure that the range of possible viewpoints is enclosed within a border of opaque geometry so that this can't happen. Failing that, you need to find some way to make the terrain blend into the skybox; this is somewhat simpler if the distant terrain is flat and featureless, e.g. sea or desert.

Dan Bartlett
07-28-2013, 01:32 AM
Have you remembered to turned off lighting when drawing the skybox?

Quaver
07-28-2013, 03:08 AM
Thanks all, it turned out that some of my texture coords where wrong and that some of the faces were back to front or upside down, disabling lighting when drawing the skybox also helped make it look better.

I have a new problem now though. Sometimes the skybox has these faint lines between each face like so:

http://s17.postimg.org/4qu3gsjb3/screen.png

How can I stop this?

EDIT: I forgot to mention that using GL_CLAMP_TO_EDGE for both my T and S wrapping modes doesn't fix the problem.

GClements
07-28-2013, 09:30 AM
I have a new problem now though. Sometimes the skybox has these faint lines between each face like so:
Is polygon anti-aliasing (GL_POLYGON_SMOOTH) enabled? If that is enabled without the correct blending mode or without an alpha buffer, it can cause the background to bleed through at shared edges.

Quaver
07-28-2013, 01:31 PM
It is off; turning it on has no effect.

trinitrotoluene
07-28-2013, 04:54 PM
Maybe you can try to enable seamless cubemap filtering (http://www.opengl.org/registry/specs/ARB/seamless_cube_map.txt) .

Alfonse Reinheart
07-28-2013, 05:05 PM
Maybe you can try to enable seamless cubemap filtering (http://www.opengl.org/registry/specs/ARB/seamless_cube_map.txt) .

That only works when using a cube map.

trinitrotoluene
07-28-2013, 05:42 PM
That only works when using a cube map.
Oups, then try with a cube map texture with seamless filtering if your graphic card can do that.

cireneikual
07-28-2013, 08:47 PM
Just move the faces inwards slightly, that should get rid of the seams.

HiMyNameIs
07-28-2013, 09:42 PM
I suggest you to use a Sphere instead of a cube to render the sky.

mhagain
07-28-2013, 11:37 PM
One way of handling seams at texture edges is to adjust the texture coords inwards, so instead of 0 use 1.0f / texture size, and instead of 1 use (texture size - 1) / texture size. Personally I'd use a cubemap texture instead.

Dan Bartlett
07-29-2013, 03:15 AM
Are your vertex coordinates still generated in the same way as the first code example you posted (but with correct values), or have you changed it since?

If you have changed it to calculate the vertex coordinates in some other way (eg. using floating point arithmetic operations, or different matrix transforms between each face), then you'll likely run into floating-point issues, where coordinates being generated aren't exactly the same, which results in overlaps/gaps between triangles.

For example, 0.6 + 0.3 is not likely to be equal to 1.2 - 0.3 when using floating point. Similarly it can be hard to get sets of vertices that are transformed by different matrices to precisely match even if they should match theoretically.

GClements
07-29-2013, 06:51 AM
One way of handling seams at texture edges is to adjust the texture coords inwards, so instead of 0 use 1.0f / texture size, and instead of 1 use (texture size - 1) / texture size. Personally I'd use a cubemap texture instead.

The main problem with that is that the texture size varies with the mipmap level.

For a skybox, the eye-space Z of any point on the skybox will always be between 1.0 and sqrt(3) ~= 1.732 "units" (the distance of the centre of each face to the centre of the cube), so you may be able to avoid mipmapping altogether, or at least determine reasonably close bounds on which levels will be used.

But in general, if you want to avoid sampling from the border you need to use GL_CLAMP_TO_EDGE.

Quaver
07-29-2013, 08:31 AM
One way of handling seams at texture edges is to adjust the texture coords inwards, so instead of 0 use 1.0f / texture size, and instead of 1 use (texture size - 1) / texture size. Personally I'd use a cubemap texture instead.

Thanks! I replaced 1.0f with 1.0f - (1.0f / 1024.0f), and 0.0f with 1.0f / 1024.0f and now the seams are gone!

mhagain
07-29-2013, 10:13 AM
The main problem with that is that the texture size varies with the mipmap level.

For a skybox, the eye-space Z of any point on the skybox will always be between 1.0 and sqrt(3) ~= 1.732 "units" (the distance of the centre of each face to the centre of the cube), so you may be able to avoid mipmapping altogether, or at least determine reasonably close bounds on which levels will be used.

But in general, if you want to avoid sampling from the border you need to use GL_CLAMP_TO_EDGE.

You shouldn't really be mipmapping a skybox anyway as it's always displayed as if it were a fixed distance from the viewpoint.

That aside, the cubemap approach really is the cleanest, as it can use any arbitrary geometry (doesn't have to be on a cube), you can use seamless cubemapping, and draw the full thing in a single draw call (rather than 6).