Forum

Skybox depthrange/farclip trick

Post tutorials on how to do certain tasks within game or engine code here.

Moderator: InsideQC Admins

Skybox depthrange/farclip trick

Postby mh » Sat May 28, 2011 11:50 pm

This one's easy; if you're drawing a skybox you normally need to worry about the far clipping plane, and that it's sufficiently large to accommodate the skybox dimensions.

But the thing is that you don't. It's actually completely unnecessary.

This one is based on the FitzQuake 0.85 code, but it's easily adaptable to any engine.

First of all, find this code block:
Code: Select all
void Sky_EmitSkyBoxVertex (float s, float t, int axis)
{
   vec3_t      v, b;
   int         j, k;
   float      w, h;

   b[0] = s * gl_farclip.value / sqrt(3.0);
   b[1] = t * gl_farclip.value / sqrt(3.0);
   b[2] = gl_farclip.value / sqrt(3.0);

Change it to:
Code: Select all
void Sky_EmitSkyBoxVertex (float s, float t, int axis)
{
   vec3_t      v, b;
   int         j, k;
   float      w, h;

   b[0] = s * 10.0f;
   b[1] = t * 10.0f;
   b[2] = 10.0f;

Now find this code block:
Code: Select all
void Sky_SetBoxVert (float s, float t, int axis, vec3_t v)
{
   vec3_t      b;
   int         j, k;

   b[0] = s * gl_farclip.value / sqrt(3.0);
   b[1] = t * gl_farclip.value / sqrt(3.0);
   b[2] = gl_farclip.value / sqrt(3.0);

And change it to:
Code: Select all
void Sky_SetBoxVert (float s, float t, int axis, vec3_t v)
{
   vec3_t      b;
   int         j, k;

   b[0] = s * 10.0f;
   b[1] = t * 10.0f;
   b[2] = 10.0f;

OK, what we're doing here is drawing the sky as a 10x10 cube instead of positioning it at the far clipping plane. Madness? Nope, because all we need to do in order to push it to the back of the depth buffer is find this code:
Code: Select all
   if (!r_fastsky.value && !(Fog_GetDensity() > 0 && r_skyfog.value >= 1))
   {
      glDepthFunc(GL_GEQUAL);
      glDepthMask(0);

      if (skybox_name[0])
         Sky_DrawSkyBox ();
      else
         Sky_DrawSkyLayers();

      glDepthMask(1);
      glDepthFunc(GL_LEQUAL);
   }

And change it to:
Code: Select all
   if (!r_fastsky.value && !(Fog_GetDensity() > 0 && r_skyfog.value >= 1))
   {
      glDepthRange (1, 1);
      glDepthFunc(GL_GEQUAL);
      glDepthMask(0);

      if (skybox_name[0])
         Sky_DrawSkyBox ();
      else
         Sky_DrawSkyLayers();

      glDepthMask(1);
      glDepthFunc(GL_LEQUAL);
      glDepthRange (0, 1);
   }

Hey-presto. Sky is now automatically positioned at the back of the scene, and you don't need to worry about your far clipping plane, positioning things correctly, or any of that. It will just automatically be correct with any scene geometry.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby metlslime » Wed Jul 13, 2011 10:03 pm

I just looked at this, and WTF -- why am i doing three sqrt() calls PER VERTEX!!!!!!!1
metlslime
 
Posts: 316
Joined: Tue Feb 05, 2008 11:03 pm

Postby Tomaz » Wed Jul 13, 2011 11:22 pm

Why not just use glDisable( GL_DEPTH_TEST ); ?

According to specs ( http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml ) it should turn off both "read" and "write" operations with the depth buffer.
Tomaz
 
Posts: 67
Joined: Fri Nov 05, 2004 8:21 pm

Postby metlslime » Thu Jul 14, 2011 1:11 am

Tomaz wrote:Why not just use glDisable( GL_DEPTH_TEST ); ?

According to specs ( http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml ) it should turn off both "read" and "write" operations with the depth buffer.


Theoretically that would work, though it would annoy me to see a big skybox floating there when i noclip outside the level.
metlslime
 
Posts: 316
Joined: Tue Feb 05, 2008 11:03 pm

Postby Spike » Thu Jul 14, 2011 2:10 am

an alternative is GL_ARB_depth_clamp / GL_NV_depth_clamp.

another alternative is as follows:
draw the skybox as the very first thing you draw, with depth testing inactive, and you get a similar result.
for bonus points, you can easily have a fastsky that clears the sky via glClear too.
which is basically what q3 does.

you likely also need to write the proper depth (glcolormask(0,0,0,0) to write just depth without colours) if you want to avoid artifacts on certain q1 maps. but that applies to any skybox/skysphere algorithm that I've seen. Many don't bother, and result in players appearing behind the sky on dm3, for example.

also, the code mh gives will conflict with gl_ztrick (you shouldn't really want to use ztrick on recent hardware, but still this should be mentioned).
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby qbism » Thu Jul 14, 2011 3:43 am

Spike wrote:players appearing behind the sky on dm3
This is a paradox which exposes the truth. Really the sky should not be visible from this viewpoint, it would be obstructed by the structure containing the exposed players.
User avatar
qbism
 
Posts: 1236
Joined: Thu Nov 04, 2004 5:51 am

Postby mh » Thu Jul 14, 2011 8:58 am

The obvious more correct way is to use a cubemap. That'll avoid all such artefacts, only draw the skybox on actual sky brushes, eliminate any fillrate concerns, and completely remove the need for any kind of depth hacking. It does need a bit of jiggery-pokery with box face image orientations at load time though.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby Tomaz » Thu Jul 14, 2011 10:02 am

metlslime wrote:
Tomaz wrote:Why not just use glDisable( GL_DEPTH_TEST ); ?

According to specs ( http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml ) it should turn off both "read" and "write" operations with the depth buffer.


Theoretically that would work, though it would annoy me to see a big skybox floating there when i noclip outside the level.


See a floating skybox where?

Obviously when doing a "no-depth" sky you render it before everything else, and have it translated to where your camera is ( view_org in Quake? been so long since last time I touched Quake code ), only downside to this that I can see is fillrate, I do something similar when rendering the regular quake sky in CleanQuake, using a sphere for the sky, rendering it first as a no-depth sky, obviously it only renders it if the Update code found a skybrush that would originally be marked to be rendered.
Tomaz
 
Posts: 67
Joined: Fri Nov 05, 2004 8:21 pm


Return to Programming Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest