Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

tr_shadows.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 #include "tr_local.h"
00023 
00024 
00025 /*
00026 
00027   for a projection shadow:
00028 
00029   point[x] += light vector * ( z - shadow plane )
00030   point[y] +=
00031   point[z] = shadow plane
00032 
00033   1 0 light[x] / light[z]
00034 
00035 */
00036 
00037 typedef struct {
00038     int     i2;
00039     int     facing;
00040 } edgeDef_t;
00041 
00042 #define MAX_EDGE_DEFS   32
00043 
00044 static  edgeDef_t   edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
00045 static  int         numEdgeDefs[SHADER_MAX_VERTEXES];
00046 static  int         facing[SHADER_MAX_INDEXES/3];
00047 
00048 void R_AddEdgeDef( int i1, int i2, int facing ) {
00049     int     c;
00050 
00051     c = numEdgeDefs[ i1 ];
00052     if ( c == MAX_EDGE_DEFS ) {
00053         return;     // overflow
00054     }
00055     edgeDefs[ i1 ][ c ].i2 = i2;
00056     edgeDefs[ i1 ][ c ].facing = facing;
00057 
00058     numEdgeDefs[ i1 ]++;
00059 }
00060 
00061 void R_RenderShadowEdges( void ) {
00062     int     i;
00063 
00064 #if 0
00065     int     numTris;
00066 
00067     // dumb way -- render every triangle's edges
00068     numTris = tess.numIndexes / 3;
00069 
00070     for ( i = 0 ; i < numTris ; i++ ) {
00071         int     i1, i2, i3;
00072 
00073         if ( !facing[i] ) {
00074             continue;
00075         }
00076 
00077         i1 = tess.indexes[ i*3 + 0 ];
00078         i2 = tess.indexes[ i*3 + 1 ];
00079         i3 = tess.indexes[ i*3 + 2 ];
00080 
00081         qglBegin( GL_TRIANGLE_STRIP );
00082         qglVertex3fv( tess.xyz[ i1 ] );
00083         qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
00084         qglVertex3fv( tess.xyz[ i2 ] );
00085         qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
00086         qglVertex3fv( tess.xyz[ i3 ] );
00087         qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] );
00088         qglVertex3fv( tess.xyz[ i1 ] );
00089         qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
00090         qglEnd();
00091     }
00092 #else
00093     int     c, c2;
00094     int     j, k;
00095     int     i2;
00096     int     c_edges, c_rejected;
00097     int     hit[2];
00098 
00099     // an edge is NOT a silhouette edge if its face doesn't face the light,
00100     // or if it has a reverse paired edge that also faces the light.
00101     // A well behaved polyhedron would have exactly two faces for each edge,
00102     // but lots of models have dangling edges or overfanned edges
00103     c_edges = 0;
00104     c_rejected = 0;
00105 
00106     for ( i = 0 ; i < tess.numVertexes ; i++ ) {
00107         c = numEdgeDefs[ i ];
00108         for ( j = 0 ; j < c ; j++ ) {
00109             if ( !edgeDefs[ i ][ j ].facing ) {
00110                 continue;
00111             }
00112 
00113             hit[0] = 0;
00114             hit[1] = 0;
00115 
00116             i2 = edgeDefs[ i ][ j ].i2;
00117             c2 = numEdgeDefs[ i2 ];
00118             for ( k = 0 ; k < c2 ; k++ ) {
00119                 if ( edgeDefs[ i2 ][ k ].i2 == i ) {
00120                     hit[ edgeDefs[ i2 ][ k ].facing ]++;
00121                 }
00122             }
00123 
00124             // if it doesn't share the edge with another front facing
00125             // triangle, it is a sil edge
00126             if ( hit[ 1 ] == 0 ) {
00127                 qglBegin( GL_TRIANGLE_STRIP );
00128                 qglVertex3fv( tess.xyz[ i ] );
00129                 qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
00130                 qglVertex3fv( tess.xyz[ i2 ] );
00131                 qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
00132                 qglEnd();
00133                 c_edges++;
00134             } else {
00135                 c_rejected++;
00136             }
00137         }
00138     }
00139 #endif
00140 }
00141 
00142 /*
00143 =================
00144 RB_ShadowTessEnd
00145 
00146 triangleFromEdge[ v1 ][ v2 ]
00147 
00148 
00149   set triangle from edge( v1, v2, tri )
00150   if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) {
00151   }
00152 =================
00153 */
00154 void RB_ShadowTessEnd( void ) {
00155     int     i;
00156     int     numTris;
00157     vec3_t  lightDir;
00158 
00159     // we can only do this if we have enough space in the vertex buffers
00160     if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) {
00161         return;
00162     }
00163 
00164     if ( glConfig.stencilBits < 4 ) {
00165         return;
00166     }
00167 
00168     VectorCopy( backEnd.currentEntity->lightDir, lightDir );
00169 
00170     // project vertexes away from light direction
00171     for ( i = 0 ; i < tess.numVertexes ; i++ ) {
00172         VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i+tess.numVertexes] );
00173     }
00174 
00175     // decide which triangles face the light
00176     Com_Memset( numEdgeDefs, 0, 4 * tess.numVertexes );
00177 
00178     numTris = tess.numIndexes / 3;
00179     for ( i = 0 ; i < numTris ; i++ ) {
00180         int     i1, i2, i3;
00181         vec3_t  d1, d2, normal;
00182         float   *v1, *v2, *v3;
00183         float   d;
00184 
00185         i1 = tess.indexes[ i*3 + 0 ];
00186         i2 = tess.indexes[ i*3 + 1 ];
00187         i3 = tess.indexes[ i*3 + 2 ];
00188 
00189         v1 = tess.xyz[ i1 ];
00190         v2 = tess.xyz[ i2 ];
00191         v3 = tess.xyz[ i3 ];
00192 
00193         VectorSubtract( v2, v1, d1 );
00194         VectorSubtract( v3, v1, d2 );
00195         CrossProduct( d1, d2, normal );
00196 
00197         d = DotProduct( normal, lightDir );
00198         if ( d > 0 ) {
00199             facing[ i ] = 1;
00200         } else {
00201             facing[ i ] = 0;
00202         }
00203 
00204         // create the edges
00205         R_AddEdgeDef( i1, i2, facing[ i ] );
00206         R_AddEdgeDef( i2, i3, facing[ i ] );
00207         R_AddEdgeDef( i3, i1, facing[ i ] );
00208     }
00209 
00210     // draw the silhouette edges
00211 
00212     GL_Bind( tr.whiteImage );
00213     qglEnable( GL_CULL_FACE );
00214     GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
00215     qglColor3f( 0.2f, 0.2f, 0.2f );
00216 
00217     // don't write to the color buffer
00218     qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
00219 
00220     qglEnable( GL_STENCIL_TEST );
00221     qglStencilFunc( GL_ALWAYS, 1, 255 );
00222 
00223     // mirrors have the culling order reversed
00224     if ( backEnd.viewParms.isMirror ) {
00225         qglCullFace( GL_FRONT );
00226         qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
00227 
00228         R_RenderShadowEdges();
00229 
00230         qglCullFace( GL_BACK );
00231         qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
00232 
00233         R_RenderShadowEdges();
00234     } else {
00235         qglCullFace( GL_BACK );
00236         qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
00237 
00238         R_RenderShadowEdges();
00239 
00240         qglCullFace( GL_FRONT );
00241         qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
00242 
00243         R_RenderShadowEdges();
00244     }
00245 
00246 
00247     // reenable writing to the color buffer
00248     qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
00249 }
00250 
00251 
00252 /*
00253 =================
00254 RB_ShadowFinish
00255 
00256 Darken everything that is is a shadow volume.
00257 We have to delay this until everything has been shadowed,
00258 because otherwise shadows from different body parts would
00259 overlap and double darken.
00260 =================
00261 */
00262 void RB_ShadowFinish( void ) {
00263     if ( r_shadows->integer != 2 ) {
00264         return;
00265     }
00266     if ( glConfig.stencilBits < 4 ) {
00267         return;
00268     }
00269     qglEnable( GL_STENCIL_TEST );
00270     qglStencilFunc( GL_NOTEQUAL, 0, 255 );
00271 
00272     qglDisable (GL_CLIP_PLANE0);
00273     qglDisable (GL_CULL_FACE);
00274 
00275     GL_Bind( tr.whiteImage );
00276 
00277     qglLoadIdentity ();
00278 
00279     qglColor3f( 0.6f, 0.6f, 0.6f );
00280     GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );
00281 
00282 //  qglColor3f( 1, 0, 0 );
00283 //  GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
00284 
00285     qglBegin( GL_QUADS );
00286     qglVertex3f( -100, 100, -10 );
00287     qglVertex3f( 100, 100, -10 );
00288     qglVertex3f( 100, -100, -10 );
00289     qglVertex3f( -100, -100, -10 );
00290     qglEnd ();
00291 
00292     qglColor4f(1,1,1,1);
00293     qglDisable( GL_STENCIL_TEST );
00294 }
00295 
00296 
00297 /*
00298 =================
00299 RB_ProjectionShadowDeform
00300 
00301 =================
00302 */
00303 void RB_ProjectionShadowDeform( void ) {
00304     float   *xyz;
00305     int     i;
00306     float   h;
00307     vec3_t  ground;
00308     vec3_t  light;
00309     float   groundDist;
00310     float   d;
00311     vec3_t  lightDir;
00312 
00313     xyz = ( float * ) tess.xyz;
00314 
00315     ground[0] = backEnd.or.axis[0][2];
00316     ground[1] = backEnd.or.axis[1][2];
00317     ground[2] = backEnd.or.axis[2][2];
00318 
00319     groundDist = backEnd.or.origin[2] - backEnd.currentEntity->e.shadowPlane;
00320 
00321     VectorCopy( backEnd.currentEntity->lightDir, lightDir );
00322     d = DotProduct( lightDir, ground );
00323     // don't let the shadows get too long or go negative
00324     if ( d < 0.5 ) {
00325         VectorMA( lightDir, (0.5 - d), ground, lightDir );
00326         d = DotProduct( lightDir, ground );
00327     }
00328     d = 1.0 / d;
00329 
00330     light[0] = lightDir[0] * d;
00331     light[1] = lightDir[1] * d;
00332     light[2] = lightDir[2] * d;
00333 
00334     for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
00335         h = DotProduct( xyz, ground ) + groundDist;
00336 
00337         xyz[0] -= light[0] * h;
00338         xyz[1] -= light[1] * h;
00339         xyz[2] -= light[2] * h;
00340     }
00341 }

Generated on Thu Aug 25 12:37:55 2005 for Quake III Arena by  doxygen 1.3.9.1