skybox problem

I have the following problem: if I want my skybox to appear without artifacts I need to scale the unit skybox cube by F / sqrt(3), so there aren’t any places on the skybox cut off at certain viewing angles. But my world is defined in an infinite cube (in fact, finite, up to the range floats allow), so such a skybox cuts a part of it away from view. More could be shown with F being the far plane distance.

My question: Is the only way to prevent the skybox from being clipped by the far plane to set F to infinity and then reset it to a finite value, that is load 2 different perspective projection matrices, first the “infinite” to draw the skybox with and prevent far-plane clipping and then the “finite” to draw the world? I have tried the glDisable(GL_DEPTH) trick but I’d like to scale the skybox even more than F / sqrt(3).

Another way is to just draw the skybox first, with depth write off and depth test off. But this causes the complete surface of the skybox to be draw, whereas a lot of parts may be covered later by the world.

Disable depth writes? This means you still need to clear the depth buffer each frame, while no need to clear the color buffer(s)? The skybox could clear the depth buffer also.

Just draw the skybox as regular world geometry rather than as a big cube surrounding the world, and use a cubemap as it’s texture instead of 6 separate face textures.

Why not draw the skybox last (more efficient, less pixel writes) and ensure depth testing is ON.

To fix your issue, simply ensure the Z of the skybox is set to the maximum value:
// Tranform to clip space.
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position.z = gl_Position.w -0.00001; //fix to far plane.

I used to draw the skybox first as it would clear the colour buffer to the skybox at the same time, but more recent articles suggested that this is a thing of the past.

// Tranform to clip space.
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position.z = gl_Position.w -0.00001; //fix to far plane.

If you have shaders, then you can do this, I don’t have them available. I could, of course, do the transform on the CPU, but that would be slow. Also, I am not certain this technique would not cause problems with the aspect ratio of skybox textures in some cases.

I used to draw the skybox first as it would clear the colour buffer to the skybox at the same time, but more recent articles suggested that this is a thing of the past.

But isn’t it nice to avoid clearing the color buffer? Anyway, I see with your technique you can draw it any time and still avoid clearing the color buffer. Maybe you can give links to the articles you mention.

I tried to avoid doing the depth buffer clear like this:


glDepthMask(0.999, 0.999);
glDisable(GL_DEPTH_TEST);
// draw the skybox
glEnable(GL_DEPTH_TEST);
glDepthMask(0, 1);

I drew the skybox first. But this doesn’t work. Why? Only the skybox appears ok, the rest of the scene is jumbled. With the approach, I tried to set the values the skybox puts into the depth buffer to the maximum. Instead of 6 2D textures, I’m using a cubemap already, thank you for the suggestion.

UPDATE: disabling GL_DEPTH_TEST disables the writes to the depth buffer. But if I clear the depth buffer and don’t disable the depth test, the glDepthRange() solution is equivalent to your shader solution, I think. Still, the shader solution is probably better/faster.

Also, I am not certain this technique would not cause problems with the aspect ratio of skybox textures in some cases.

How could it? There is no rotational transform applied after the vertex shader. The X/Y/W coordinates in clip-space that the vertex shader outputs define what the window-space X/Y coordinates will be. Modifying the Z cannot change them and therefore cannot change the aspect ratio.

But isn’t it nice to avoid clearing the color buffer?

Why? If clearing the color buffer doesn’t actually take time, then why would it matter?

Though if you’re working with pre-shader hardware (anything before GeForce 3), then you probably should look to recommendations made for hardware of the era you’re working with.

How could it? There is no rotational transform applied after the vertex shader. The X/Y/W coordinates in clip-space that the vertex shader outputs define what the window-space X/Y coordinates will be. Modifying the Z cannot change them and therefore cannot change the aspect ratio.

I see this now, thanks. The z is faked to please the clipper.

Why? If clearing the color buffer doesn’t actually take time, then why would it matter?

Though if you’re working with pre-shader hardware (anything before GeForce 3), then you probably should look to recommendations made for hardware of the era you’re working with.

Doesn’t it? I didn’t know that. Or rather, I thought that filling the color buffer with some value would take some time. I’m pretty certain many games don’t clear the color buffer.

I think the problem with glDepthRange(1, 1) is that I need to disable the depth test. But disabling the depth test disables the writes into the depth buffer too.

That was true 10 years ago. Now clears are very fast. Try to benchmark it on your hardware if you still have doubts.

Indeed glDisable(GL_DEPTH_TEST) does disable both reads and writes. But you can do this to ‘write-only’ :

glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_ALWAYS );

Indeed glDisable(GL_DEPTH_TEST) does disable both reads and writes.[/QUOTE]
What?! :eek: Wow! Never heard or read that before, and intuitively it doesn’t make sense. Though I confess to have just found the language in the spec that appears to say what you just said.

I always thought the way to write depth without depth tests was simply.

glDisable( GL_DEPTH_TEST );
glDepthMask( GL_TRUE );

So you’re saying glDepthMask (depth write Y/N) has absolutely no effect unless GL_DEPTH_TEST is “enabled”? So GL_DEPTH_TEST is really GL_DEPTH_TEST_AND_WRITE, with glDepthMask toggling the write part?

Now that no depth buffer clear is necessary I’ll still have to bench if it’s worth it to clear it via a skybox.

You’d probably say that for modern hardware it’s not.

the logic in the API was the following:

  • the depth unit is really a “read modify write” (in HW)
  • when you disable depth, then you disable the entire thing.

as for performance recommendation:

  • for depth/color clear, it is much better to use the API glClear, since it usually allows the HW to apply some smart compression. (hint: the HW does not necessarily write every color/depth value in memory)
  • if you draw a quad instead, there will be some level of compression (depth is always compressed, and in msaa color is easily compressed)
  • usually the performance difference is not large on latest high end because there is lots of bandwidth and we can touch ~32 pixels/clock at full speed (even much more for depth)
  • but on lower end HW, saving memory transaction is always interesting (can be 10% …)
  • with fusion type ASIC, there will be a very large user base with good GPU performance but not high end bandwidth, so will matter again

Thanks. Good info. Also an issue is what techniques reset Hi-Z/ZCULL. Re your last point, I’d wondered about that with Bobcat/Bulldozer/Sandy Bridge. Will be interesting to see where the fill shakes out against a stand-alone GPU.