Code: Select all
/*
=================
R_DrawSkyArrays
=================
*/
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
GL_Bind (texnum);
// draw the sphere
// (if this barfs on your implementation, just unroll the single call into 10 batches of 22)
glCallList (r_skysphere);
// restore the previous matrix
glPopMatrix ();
}
/*
=================
R_ClipSky
eh not sure this was the intention ?
=================
*/
void R_ClipSky (msurface_t *fa)
{
// disable texturing and writes to the color buffer
glDisable (GL_TEXTURE_2D);
glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
for (fa = skychain; fa; fa = fa->texturechain)
{
EmitFlatPoly (fa);
}
skychain = NULL;
skychain_tail = &skychain;
// 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);
}
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (void)
{
// sky scaling
float fullscale = r_farclip.value / 4096;
float halfscale = r_farclip.value / 8192;
float reducedfull = (r_farclip.value / 4096) * 0.9;
float reducedhalf = (r_farclip.value / 8192) * 0.9;
// rotation
float rotateBack = anglemod (realtime * 6); // JT022605 - changed from 12 to slow sky
float rotateFore = anglemod (realtime * 10); // JT022605 - changed from 20 to slow sky
if (!skychain) return;
// turn on fogging. fog looks good on the skies - it gives them a more
// "airy" far-away look, and has the knock-on effect of preventing the
// old "texture distortion at the poles" problem.
glFogi (GL_FOG_MODE, GL_LINEAR);
glFogfv (GL_FOG_COLOR, r_skyfog);
glFogf (GL_FOG_START, -r_farclip.value); // changed from 5
// must tweak the fog end too!!!
glFogf (GL_FOG_END, r_farclip.value * 0.60); // changed from 0.75
glEnable (GL_FOG);
// write the regular sky polys into the depth buffer to get a baseline
R_ClipSky (skychain);
// 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
// previous releases made a tiled version of the sky texture. here i just shrink it using the
// texture matrix, for much the same effect
glMatrixMode (GL_TEXTURE);
glLoadIdentity ();
glScalef (2, 1, 1);
glMatrixMode (GL_MODELVIEW);
// background
// ==========
// go to a new matrix
R_DrawSkyArrays (solidskytexture, reducedfull, reducedhalf, -rotateBack);
// enable blending for the alpha sky
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// foreground
// ==========
// go to a new matrix
R_DrawSkyArrays (alphaskytexture, fullscale, halfscale, -rotateFore);
// back to normal mode
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable (GL_BLEND);
// turn off fog
glDisable (GL_FOG);
// 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
R_ClipSky (skychain);
}
/*
==============
R_DrawSphere
Draw a sphere!!! The verts and texcoords are precalculated for extra efficiency. The sphere is put into
a display list to reduce overhead even further.
==============
*/
float skytexes[440];
float skyverts[660];
void R_DrawSphere (void)
{
if (r_skysphere == -1)
{
int i;
int j;
int vertspos = 0;
int texespos = 0;
// build the sphere display list
r_skysphere = glGenLists (1);
glNewList (r_skysphere, GL_COMPILE);
for (i = 0; i < 10; i++)
{
glBegin (GL_TRIANGLE_STRIP);
for (j = 0; j <= 10; j++)
{
glTexCoord2fv (&skytexes[texespos]);
glVertex3fv (&skyverts[vertspos]);
texespos += 2;
vertspos += 3;
glTexCoord2fv (&skytexes[texespos]);
glVertex3fv (&skyverts[vertspos]);
texespos += 2;
vertspos += 3;
}
glEnd ();
}
glEndList ();
}
}
/*
==============
R_InitSkyChain
Initialize the sky chain arrays
==============
*/
void R_InitSkyChain (void)
{
float drho = 0.3141592653589;
float dtheta = 0.6283185307180;
float ds = 0.1;
float dt = 0.1;
float t = 1.0f;
float s = 0.0f;
int i;
int j;
int vertspos = 0;
int texespos = 0;
for (i = 0; i < 10; i++)
{
float rho = (float) i * drho;
float srho = (float) (sin (rho));
float crho = (float) (cos (rho));
float srhodrho = (float) (sin (rho + drho));
float crhodrho = (float) (cos (rho + drho));
s = 0.0f;
for (j = 0; j <= 10; j++)
{
float theta = (j == 10) ? 0.0f : j * dtheta;
float stheta = (float) (-sin( theta));
float ctheta = (float) (cos (theta));
skytexes[texespos++] = s * 2;
skytexes[texespos++] = t * 2;
skyverts[vertspos++] = stheta * srho * 4096.0;
skyverts[vertspos++] = ctheta * srho * 4096.0;
skyverts[vertspos++] = crho * 4096.0;
skytexes[texespos++] = s * 2;
skytexes[texespos++] = (t - dt) * 2;
skyverts[vertspos++] = stheta * srhodrho * 4096.0;
skyverts[vertspos++] = ctheta * srhodrho * 4096.0;
skyverts[vertspos++] = crhodrho * 4096.0;
s += ds;
}
t -= dt;
}
}
/*
=============
R_InitSky
A sky texture is 256*128, with the right side being a masked overlay
==============
*/
void R_InitSky (miptex_t *mt)
{
int i, j, p;
byte *src;
unsigned transpix;
int r, g, b;
unsigned *rgba;
unsigned topalpha;
int div;
unsigned *trans;
// initialize our pointers
trans = malloc (128 * 128 * 4);
// -----------------
// solid sky texture
// -----------------
src = (byte *)mt + mt->offsets[0];
// make an average value for the back to avoid
// a fringe on the top level
r = g = b = 0;
for (i=0 ; i<128 ; i++)
{
for (j=0 ; j<128 ; j++)
{
p = src[i*256 + j + 128];
rgba = &d_8to24table[p];
trans[(i*128) + j] = *rgba;
r += ((byte *)rgba)[0];
g += ((byte *)rgba)[1];
b += ((byte *)rgba)[2];
}
}
((byte *)&transpix)[0] = r/(128*128);
((byte *)&transpix)[1] = g/(128*128);
((byte *)&transpix)[2] = b/(128*128);
((byte *)&transpix)[3] = 0;
if (!solidskytexture) solidskytexture = texture_extension_number++;
GL_Bind (solidskytexture);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// -----------------
// alpha sky texture
// -----------------
// get another average cos the bottom layer average can be too dark
div = r = g = b = 0;
for (i=0 ; i<128 ; i++)
{
for (j=0 ; j<128 ; j++)
{
p = src[i*256 + j];
if (p == 0)
{
topalpha = transpix;
}
else
{
rgba = &d_8to24table[p];
r += ((byte *)rgba)[0];
g += ((byte *)rgba)[1];
b += ((byte *)rgba)[2];
div++;
topalpha = d_8to24table[p];
}
((byte *)&topalpha)[3] = ((byte *)&topalpha)[3] / 2;
trans[(i*128) + j] = topalpha;
}
}
if (!alphaskytexture) alphaskytexture = texture_extension_number++;
GL_Bind (alphaskytexture);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// get fog colours for the sky - we halve these
r_skyfog[0] = ((float)r / (float)div) / 512.0;
r_skyfog[1] = ((float)g / (float)div) / 512.0;
r_skyfog[2] = ((float)b / (float)div) / 512.0;
r_skyfog[3] = 0.1;
// free the used memory
free (trans);
// recalc the sphere display list - delete the original one first!!!
if (r_skysphere != -1)
{
glDeleteLists (r_skysphere, 1);
}
r_skysphere = -1;
R_InitSkyChain ();
R_DrawSphere ();
}