tr_shadows.c (7900B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 #include "tr_local.h" 23 24 25 /* 26 27 for a projection shadow: 28 29 point[x] += light vector * ( z - shadow plane ) 30 point[y] += 31 point[z] = shadow plane 32 33 1 0 light[x] / light[z] 34 35 */ 36 37 typedef struct { 38 int i2; 39 int facing; 40 } edgeDef_t; 41 42 #define MAX_EDGE_DEFS 32 43 44 static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS]; 45 static int numEdgeDefs[SHADER_MAX_VERTEXES]; 46 static int facing[SHADER_MAX_INDEXES/3]; 47 48 void R_AddEdgeDef( int i1, int i2, int facing ) { 49 int c; 50 51 c = numEdgeDefs[ i1 ]; 52 if ( c == MAX_EDGE_DEFS ) { 53 return; // overflow 54 } 55 edgeDefs[ i1 ][ c ].i2 = i2; 56 edgeDefs[ i1 ][ c ].facing = facing; 57 58 numEdgeDefs[ i1 ]++; 59 } 60 61 void R_RenderShadowEdges( void ) { 62 int i; 63 64 #if 0 65 int numTris; 66 67 // dumb way -- render every triangle's edges 68 numTris = tess.numIndexes / 3; 69 70 for ( i = 0 ; i < numTris ; i++ ) { 71 int i1, i2, i3; 72 73 if ( !facing[i] ) { 74 continue; 75 } 76 77 i1 = tess.indexes[ i*3 + 0 ]; 78 i2 = tess.indexes[ i*3 + 1 ]; 79 i3 = tess.indexes[ i*3 + 2 ]; 80 81 qglBegin( GL_TRIANGLE_STRIP ); 82 qglVertex3fv( tess.xyz[ i1 ] ); 83 qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); 84 qglVertex3fv( tess.xyz[ i2 ] ); 85 qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); 86 qglVertex3fv( tess.xyz[ i3 ] ); 87 qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] ); 88 qglVertex3fv( tess.xyz[ i1 ] ); 89 qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); 90 qglEnd(); 91 } 92 #else 93 int c, c2; 94 int j, k; 95 int i2; 96 int c_edges, c_rejected; 97 int hit[2]; 98 99 // an edge is NOT a silhouette edge if its face doesn't face the light, 100 // or if it has a reverse paired edge that also faces the light. 101 // A well behaved polyhedron would have exactly two faces for each edge, 102 // but lots of models have dangling edges or overfanned edges 103 c_edges = 0; 104 c_rejected = 0; 105 106 for ( i = 0 ; i < tess.numVertexes ; i++ ) { 107 c = numEdgeDefs[ i ]; 108 for ( j = 0 ; j < c ; j++ ) { 109 if ( !edgeDefs[ i ][ j ].facing ) { 110 continue; 111 } 112 113 hit[0] = 0; 114 hit[1] = 0; 115 116 i2 = edgeDefs[ i ][ j ].i2; 117 c2 = numEdgeDefs[ i2 ]; 118 for ( k = 0 ; k < c2 ; k++ ) { 119 if ( edgeDefs[ i2 ][ k ].i2 == i ) { 120 hit[ edgeDefs[ i2 ][ k ].facing ]++; 121 } 122 } 123 124 // if it doesn't share the edge with another front facing 125 // triangle, it is a sil edge 126 if ( hit[ 1 ] == 0 ) { 127 qglBegin( GL_TRIANGLE_STRIP ); 128 qglVertex3fv( tess.xyz[ i ] ); 129 qglVertex3fv( tess.xyz[ i + tess.numVertexes ] ); 130 qglVertex3fv( tess.xyz[ i2 ] ); 131 qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); 132 qglEnd(); 133 c_edges++; 134 } else { 135 c_rejected++; 136 } 137 } 138 } 139 #endif 140 } 141 142 /* 143 ================= 144 RB_ShadowTessEnd 145 146 triangleFromEdge[ v1 ][ v2 ] 147 148 149 set triangle from edge( v1, v2, tri ) 150 if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) { 151 } 152 ================= 153 */ 154 void RB_ShadowTessEnd( void ) { 155 int i; 156 int numTris; 157 vec3_t lightDir; 158 159 // we can only do this if we have enough space in the vertex buffers 160 if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) { 161 return; 162 } 163 164 if ( glConfig.stencilBits < 4 ) { 165 return; 166 } 167 168 VectorCopy( backEnd.currentEntity->lightDir, lightDir ); 169 170 // project vertexes away from light direction 171 for ( i = 0 ; i < tess.numVertexes ; i++ ) { 172 VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i+tess.numVertexes] ); 173 } 174 175 // decide which triangles face the light 176 Com_Memset( numEdgeDefs, 0, 4 * tess.numVertexes ); 177 178 numTris = tess.numIndexes / 3; 179 for ( i = 0 ; i < numTris ; i++ ) { 180 int i1, i2, i3; 181 vec3_t d1, d2, normal; 182 float *v1, *v2, *v3; 183 float d; 184 185 i1 = tess.indexes[ i*3 + 0 ]; 186 i2 = tess.indexes[ i*3 + 1 ]; 187 i3 = tess.indexes[ i*3 + 2 ]; 188 189 v1 = tess.xyz[ i1 ]; 190 v2 = tess.xyz[ i2 ]; 191 v3 = tess.xyz[ i3 ]; 192 193 VectorSubtract( v2, v1, d1 ); 194 VectorSubtract( v3, v1, d2 ); 195 CrossProduct( d1, d2, normal ); 196 197 d = DotProduct( normal, lightDir ); 198 if ( d > 0 ) { 199 facing[ i ] = 1; 200 } else { 201 facing[ i ] = 0; 202 } 203 204 // create the edges 205 R_AddEdgeDef( i1, i2, facing[ i ] ); 206 R_AddEdgeDef( i2, i3, facing[ i ] ); 207 R_AddEdgeDef( i3, i1, facing[ i ] ); 208 } 209 210 // draw the silhouette edges 211 212 GL_Bind( tr.whiteImage ); 213 qglEnable( GL_CULL_FACE ); 214 GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); 215 qglColor3f( 0.2f, 0.2f, 0.2f ); 216 217 // don't write to the color buffer 218 qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); 219 220 qglEnable( GL_STENCIL_TEST ); 221 qglStencilFunc( GL_ALWAYS, 1, 255 ); 222 223 // mirrors have the culling order reversed 224 if ( backEnd.viewParms.isMirror ) { 225 qglCullFace( GL_FRONT ); 226 qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); 227 228 R_RenderShadowEdges(); 229 230 qglCullFace( GL_BACK ); 231 qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); 232 233 R_RenderShadowEdges(); 234 } else { 235 qglCullFace( GL_BACK ); 236 qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); 237 238 R_RenderShadowEdges(); 239 240 qglCullFace( GL_FRONT ); 241 qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); 242 243 R_RenderShadowEdges(); 244 } 245 246 247 // reenable writing to the color buffer 248 qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); 249 } 250 251 252 /* 253 ================= 254 RB_ShadowFinish 255 256 Darken everything that is is a shadow volume. 257 We have to delay this until everything has been shadowed, 258 because otherwise shadows from different body parts would 259 overlap and double darken. 260 ================= 261 */ 262 void RB_ShadowFinish( void ) { 263 if ( r_shadows->integer != 2 ) { 264 return; 265 } 266 if ( glConfig.stencilBits < 4 ) { 267 return; 268 } 269 qglEnable( GL_STENCIL_TEST ); 270 qglStencilFunc( GL_NOTEQUAL, 0, 255 ); 271 272 qglDisable (GL_CLIP_PLANE0); 273 qglDisable (GL_CULL_FACE); 274 275 GL_Bind( tr.whiteImage ); 276 277 qglLoadIdentity (); 278 279 qglColor3f( 0.6f, 0.6f, 0.6f ); 280 GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO ); 281 282 // qglColor3f( 1, 0, 0 ); 283 // GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); 284 285 qglBegin( GL_QUADS ); 286 qglVertex3f( -100, 100, -10 ); 287 qglVertex3f( 100, 100, -10 ); 288 qglVertex3f( 100, -100, -10 ); 289 qglVertex3f( -100, -100, -10 ); 290 qglEnd (); 291 292 qglColor4f(1,1,1,1); 293 qglDisable( GL_STENCIL_TEST ); 294 } 295 296 297 /* 298 ================= 299 RB_ProjectionShadowDeform 300 301 ================= 302 */ 303 void RB_ProjectionShadowDeform( void ) { 304 float *xyz; 305 int i; 306 float h; 307 vec3_t ground; 308 vec3_t light; 309 float groundDist; 310 float d; 311 vec3_t lightDir; 312 313 xyz = ( float * ) tess.xyz; 314 315 ground[0] = backEnd.or.axis[0][2]; 316 ground[1] = backEnd.or.axis[1][2]; 317 ground[2] = backEnd.or.axis[2][2]; 318 319 groundDist = backEnd.or.origin[2] - backEnd.currentEntity->e.shadowPlane; 320 321 VectorCopy( backEnd.currentEntity->lightDir, lightDir ); 322 d = DotProduct( lightDir, ground ); 323 // don't let the shadows get too long or go negative 324 if ( d < 0.5 ) { 325 VectorMA( lightDir, (0.5 - d), ground, lightDir ); 326 d = DotProduct( lightDir, ground ); 327 } 328 d = 1.0 / d; 329 330 light[0] = lightDir[0] * d; 331 light[1] = lightDir[1] * d; 332 light[2] = lightDir[2] * d; 333 334 for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) { 335 h = DotProduct( xyz, ground ) + groundDist; 336 337 xyz[0] -= light[0] * h; 338 xyz[1] -= light[1] * h; 339 xyz[2] -= light[2] * h; 340 } 341 }