mh's zfail skypheres port to normal quake
Posted: Thu Feb 28, 2008 4:57 pm
not sure they are correct they do work tho one function in particualr had me up the walls the code for clipping sky see below maybe if mh drops by he can spread some light as to what actually needs to be there, as of right now i just render two passes ontop.
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 ();
}