Inside3D!
     

3D Skyboxes
Goto page Previous  1, 2
 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Engine Programming
View previous topic :: View next topic  
Author Message
Sajt



Joined: 16 Oct 2004
Posts: 1026

PostPosted: Sat Jan 05, 2008 2:14 am    Post subject: Reply with quote

The reason for using skyrooms is to include actual geometry like mountains and distant buildings. Your 'skydome' idea sounds pretty much like what Quake has by default. The reason for multiple skyrooms is you can have some nearby distant buildings in one, then distant distant buildings in another, or something similar. Mappers could think of more ingenious and trippy uses for it.

A skyroom is not 'worse' than a '2D skybox'. A regular skybox can be replicated by just making a textured box and putting the view origin in the middle, and setting the parallax scroll factor (or whatever) to 0.

The only benefit I can see for the 'only one skyroom allowed' hack is that Quake has no good way for you to specify which skyroom a sky polygon should point to... (barring more hacks)
_________________
F. A. Špork, an enlightened nobleman and a great patron of art, had a stately Baroque spa complex built on the banks of the River Labe.
Back to top
View user's profile Send private message
Preach



Joined: 25 Nov 2004
Posts: 122

PostPosted: Sat Jan 05, 2008 2:45 am    Post subject: Reply with quote

But you could put the near-distant and the distant buildings into the same skyroom and achieve the same effect, it's unnecessary.
Back to top
View user's profile Send private message
Sajt



Joined: 16 Oct 2004
Posts: 1026

PostPosted: Sat Jan 05, 2008 3:16 am    Post subject: Reply with quote

Your face is unnecessary.
_________________
F. A. Špork, an enlightened nobleman and a great patron of art, had a stately Baroque spa complex built on the banks of the River Labe.
Back to top
View user's profile Send private message
mh



Joined: 12 Jan 2008
Posts: 909

PostPosted: Wed Jan 16, 2008 7:03 pm    Post subject: Reply with quote

Spike wrote:
Just draw the sky surfaces like normal... except draw them first and turn the colour buffer writes off. glColorMask(0,0,0,0). then when you draw the rest of the world, the normal z buffer tests will prevent anything behind the sky from being drawn.

That's an interesting trick. You can also use a variation on it to mask out sky polys that would otherwise be covered by the world, very useful if you have to render a full rotating sky box or sky sphere.

The process is:

* Draw regular sky polys with colormask 0.
* Invert the depth func.
* Draw the box/sphere/whatever. For a dual layer box/sphere, draw the back layer nearer than the front, to match the inverted depth func.
* Switch the depth func back to normal.
* Draw regular sky polys with colormask 0 again.
* Draw the world.

Here it is in the start room of e4m7 (with the world render turned off):



And here's code for a working implementation (based off my previous sky sphere tutorial on QuakeSrc.org, so if you've implemented that you should be able to do this too):

Code:
/*
=================
R_DrawSkyChain
=================
*/
cvar_t r_skyspeed = {"r_skyspeed", "2.5", true};

float rotateBack = 0;
float rotateFore = 0;

float skytexes[440];
float skyverts[660];

void R_DrawSkyArrays (int texnum, float bigscale, float smallscale, float rotatefactor)
{
   // go to a new matrix
   glPushMatrix ();

   // center it on the players position, scale it, orient so the poles are unobtrusive,
   // make it not always at right angles to the player, and rotate it around the poles
   glTranslatef (r_origin[0], r_origin[1], r_origin[2]);
   glTranslatef (0, 0, -500);
   glScalef (bigscale, bigscale, smallscale);
   glRotatef (-90, 1, 0, 0);
   glRotatef (-22, 0, 1, 0);
   glRotatef (rotatefactor, 0, 0, 1);

   // bind the correct texture
   glBindTexture (GL_TEXTURE_2D, texnum);

   // draw the sphere
   // (if this barfs on your implementation, just unroll the single call into 10 batches of 22)
   glDrawArrays (GL_TRIANGLE_STRIP, 0, 220);

   // restore the previous matrix
   glPopMatrix ();
}


void R_ClipSky (msurface_t *skychain)
{
   int i;
   glvertex_t *v;
   msurface_t   *surf;
   glpoly_t *p;

   // disable texturing and writes to the color buffer
   glDisable (GL_TEXTURE_2D);
   glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

   for (surf = skychain; surf; surf = surf->texturechain)
   {
      for (p = surf->polys; p; p = p->next)
      {
         int vpos = 0;

         for (i = 0, v = p->verts; i < p->numverts; i++, v++)
         {
            VArrayVerts[vpos++] = v->tv[0];
            VArrayVerts[vpos++] = v->tv[1];
            VArrayVerts[vpos++] = v->tv[2];
         }

         glDrawArrays (GL_TRIANGLE_FAN, 0, p->numverts);
      }
   }

   // revert
   glEnable (GL_TEXTURE_2D);
   glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

   // need to reset primary colour to full as well
   // as colormask can set it to black on some implementations
   glColor3f (1, 1, 1);
}


void R_DrawSkyChain (msurface_t *skychain)
{
   // sky scaling
   float fullscale;
   float halfscale;
   float reducedfull;
   float reducedhalf;

   // do these calcs even if we're not drawing
   // sky rotation
   // bound rotation speed 0 to 100
   if (r_skyspeed.value < 0) r_skyspeed.value = 0;
   if (r_skyspeed.value > 100) r_skyspeed.value = 100;

   // always rotate even if we're paused!!!
   rotateBack = anglemod (realtime * (2.5 * r_skyspeed.value));
   rotateFore = anglemod (realtime * (4.0 * r_skyspeed.value));

   // no sky to draw
   if (!skychain) return;

   // need this as a baseline for everything
   glEnableClientState (GL_VERTEX_ARRAY);
   glVertexPointer (3, GL_FLOAT, sizeof (float) * 3, VArrayVerts);

   // write the regular sky polys into the depth buffer to get a baseline
   R_ClipSky (skychain);

   // calculate the scales in proportion to the far clipping plane for the world
   fullscale = r_farclip / 4096;
   halfscale = r_farclip / 8192;
   reducedfull = (r_farclip / 4096) * 0.9;
   reducedhalf = (r_farclip / 8192) * 0.9;

   // switch the depth func so that the regular polys will prevent sphere polys outside their area reaching the framebuffer
   glDepthFunc (GL_GEQUAL);
   glDepthMask (GL_FALSE);

   // sky texture scaling
   // note that in terms of size this is *NOT* visually the same as the "classic" quake sky - drawing it on a
   // proper sphere generates an "obviously a tiled texture" look if we shrink it more, and looks very wrong,
   // so we go for somewhat larger instead.  increase to 8, 4, 4 if that really bothers you.
   glMatrixMode (GL_TEXTURE);
   glLoadIdentity ();
   glScalef (6, 3, 3);
   glMatrixMode (GL_MODELVIEW);

   // switch vertex pointers
   glVertexPointer (3, GL_FLOAT, 3 * sizeof (float), skyverts);

   glEnableClientState (GL_TEXTURE_COORD_ARRAY);
   glTexCoordPointer (2, GL_FLOAT, 2 * sizeof (float), skytexes);

   // background
   // here we invert the sphere sizes to match the inverted depth func, so that the smaller sphere is actually the back texture!
   R_DrawSkyArrays (solidskytexture->texnum, reducedfull, reducedhalf, -rotateBack);

   // enable blending for the alpha sky
   glEnable (GL_BLEND);
   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   // foreground
   // here we invert the sphere sizes to match the inverted depth func, so that the larger sphere is actually the front texture!
   R_DrawSkyArrays (alphaskytexture->texnum, fullscale, halfscale, -rotateFore);

   // back to normal mode
   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glDisable (GL_BLEND);

   // done with texturing
   glDisableClientState (GL_TEXTURE_COORD_ARRAY);

   // revert the texture matrix
   glMatrixMode (GL_TEXTURE);
   glLoadIdentity ();
   glMatrixMode (GL_MODELVIEW);

   // revert the depth func
   glDepthFunc (GL_LEQUAL);
   glDepthMask (GL_TRUE);

   // now write the regular polys one more time to clip world geometry
   glVertexPointer (3, GL_FLOAT, sizeof (float) * 3, VArrayVerts);

   R_ClipSky (skychain);

   // done!  phew!  opengl-fu at it's finest
   glDisableClientState (GL_VERTEX_ARRAY);

   // run a pipeline flush
   GL_FlushOrFinish (false);
}
Back to top
View user's profile Send private message Visit poster's website
frag.machine



Joined: 25 Nov 2006
Posts: 728

PostPosted: Wed Jan 16, 2008 10:10 pm    Post subject: Reply with quote

Hey, MH is in da house! Very Happy
_________________
frag.machine - Q2K4 Project
http://fragmachine.quakedev.com/
Back to top
View user's profile Send private message Visit poster's website
leileilol



Joined: 15 Oct 2004
Posts: 1321

PostPosted: Thu Jan 17, 2008 4:23 am    Post subject: Reply with quote

I remember seeing a gl_skyroom.c in mrGlQuake once
_________________
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Engine Programming All times are GMT
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group