/* * R_SurfaceShadowBits */ static unsigned int R_SurfaceShadowBits( const msurface_t *surf, unsigned int checkShadowBits ) { unsigned int i, bit; shadowGroup_t *grp; unsigned int surfShadowBits = 0; if( !R_SurfPotentiallyShadowed( surf ) ) { return 0; } for( i = 0; i < rsc.numShadowGroups; i++ ) { if( !checkShadowBits ) { break; } grp = rsc.shadowGroups + i; bit = grp->bit; if( checkShadowBits & bit ) { switch( surf->facetype ) { case FACETYPE_PLANAR: if ( BoundsIntersect( surf->mins, surf->maxs, grp->visMins, grp->visMaxs ) ) { float dist = PlaneDiff( grp->visOrigin, surf->plane ); if ( dist > -grp->visRadius && dist <= grp->visRadius ) { // crossed by plane surfShadowBits |= bit; } } break; case FACETYPE_PATCH: case FACETYPE_TRISURF: case FACETYPE_FOLIAGE: if( BoundsIntersect( surf->mins, surf->maxs, grp->visMins, grp->visMaxs ) ) { surfShadowBits |= bit; } break; } checkShadowBits &= ~bit; } } return surfShadowBits; }
/* * R_AddSurfaceToDrawList */ static void R_AddSurfaceToDrawList( const entity_t *e, const msurface_t *surf, const mfog_t *fog, unsigned int clipFlags, unsigned int dlightBits, unsigned shadowBits, float dist ) { int order = 0; shader_t *shader; drawSurfaceBSP_t *drawSurf; if( R_CullSurface( e, surf, clipFlags ) ) { return; } if( r_drawworld->integer == 2 ) { shader = rsh.envShader; } else { shader = surf->shader; if( shader->flags & SHADER_SKY ) { if( !R_FASTSKY() ) { R_AddSkyToDrawList( surf ); rn.numVisSurfaces++; } return; } } drawSurf = surf->drawSurf; if( drawSurf->visFrame != rf.frameCount ) { portalSurface_t *portalSurface = NULL; if( shader->flags & SHADER_PORTAL ) { // draw portals in front-to-back order dist = 1024 - dist / 100.0f; if( dist < 1 ) dist = 1; portalSurface = R_AddPortalSurface( e, surf->mesh, surf->mins, surf->maxs, shader ); } drawSurf->visFrame = rf.frameCount; if( !R_AddDSurfToDrawList( e, fog, shader, dist, order, portalSurface, drawSurf ) ) { return; } } // keep track of the actual vbo chunk we need to render R_AddVBOSlice( drawSurf - rsh.worldBrushModel->drawSurfaces, surf->mesh->numVerts, surf->mesh->numElems, surf->firstDrawSurfVert, surf->firstDrawSurfElem ); // dynamic lights that affect the surface if( dlightBits && R_SurfPotentiallyLit( surf ) ) { // ignore dlights that have already been marked as affectors if( drawSurf->dlightFrame == rsc.frameCount ) { drawSurf->dlightBits |= dlightBits; } else { drawSurf->dlightBits = dlightBits; drawSurf->dlightFrame = rsc.frameCount; } } // shadows that are projected onto the surface if( shadowBits && R_SurfPotentiallyShadowed( surf ) ) { // ignore shadows that have already been marked as affectors if( drawSurf->shadowFrame == rsc.frameCount ) { drawSurf->shadowBits |= shadowBits; } else { drawSurf->shadowBits = shadowBits; drawSurf->shadowFrame = rsc.frameCount; } } rf.stats.c_brush_polys++; rn.numVisSurfaces++; }
/* * R_AddBrushModelToDrawList */ bool R_AddBrushModelToDrawList( const entity_t *e ) { unsigned int i; vec3_t origin; vec3_t bmins, bmaxs; bool rotated; model_t *model = e->model; mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata; msurface_t *surf; mfog_t *fog; float radius, distance; unsigned int bit, fullBits; unsigned int dlightBits, shadowBits; if( bmodel->nummodelsurfaces == 0 ) { return false; } radius = R_BrushModelBBox( e, bmins, bmaxs, &rotated ); if( R_CullModelEntity( e, bmins, bmaxs, radius, rotated, false ) ) { return false; } // never render weapon models or non-occluders into shadowmaps if( rn.renderFlags & RF_SHADOWMAPVIEW ) { if( rsc.entShadowGroups[R_ENT2NUM(e)] != rn.shadowGroup->id ) { return true; } } VectorAdd( e->model->mins, e->model->maxs, origin ); VectorMA( e->origin, 0.5, origin, origin ); distance = Distance( origin, rn.refdef.vieworg ); fog = R_FogForBounds( bmins, bmaxs ); R_TransformPointToModelSpace( e, rotated, rn.refdef.vieworg, modelOrg ); // check dynamic lights that matter in the instance against the model dlightBits = 0; for( i = 0, fullBits = rn.dlightBits, bit = 1; fullBits; i++, fullBits &= ~bit, bit <<= 1 ) { if( !( fullBits & bit ) ) { continue; } if( !BoundsAndSphereIntersect( bmins, bmaxs, rsc.dlights[i].origin, rsc.dlights[i].intensity ) ) { continue; } dlightBits |= bit; } // check shadowmaps that matter in the instance against the model shadowBits = 0; for( i = 0, fullBits = rn.shadowBits; fullBits; i++, fullBits &= ~bit ) { shadowGroup_t *grp = rsc.shadowGroups + i; bit = grp->bit; if( !( fullBits & bit ) ) { continue; } if( !BoundsIntersect( bmins, bmaxs, grp->visMins, grp->visMaxs ) ) { continue; } shadowBits |= bit; } for( i = 0, surf = bmodel->firstmodelsurface; i < bmodel->nummodelsurfaces; i++, surf++ ) { int surfDlightBits, surfShadowBits; if( !surf->drawSurf ) { continue; } if( surf->visFrame != rf.frameCount ) { surf->visFrame = rf.frameCount; surfDlightBits = R_SurfPotentiallyLit( surf ) ? dlightBits : 0; surfShadowBits = R_SurfPotentiallyShadowed( surf ) ? shadowBits : 0; R_AddSurfaceToDrawList( e, surf, fog, 0, surfDlightBits, surfShadowBits, distance ); } } return true; }
/* * R_AddSurfaceToDrawList */ static void R_AddSurfaceToDrawList( const entity_t *e, const msurface_t *surf, const mfog_t *fog, unsigned int clipFlags, unsigned int dlightBits, unsigned shadowBits, float dist ) { int order = 0; shader_t *shader; drawSurfaceBSP_t *drawSurf; if( R_CullSurface( e, surf, clipFlags ) ) { return; } if( r_drawworld->integer == 2 ) { shader = rf.envShader; } else { shader = surf->shader; if( shader->flags & SHADER_SKY ) { if( !R_FASTSKY() ) { R_AddSkyToDrawList( surf ); } // fallthrough, but add with skyclip shader, writing to depthbuffer // that will mask our skydome and prevent world geometry from // bleeding through it fog = NULL; shader = rf.skyclipShader; order = 1000; } } drawSurf = surf->drawSurf; if( drawSurf->visFrame != r_framecount ) { portalSurface_t *portalSurface = NULL; if( shader->flags & SHADER_PORTAL ) { portalSurface = R_AddPortalSurface( e, surf->mesh, surf->mins, surf->maxs, shader ); } drawSurf->visFrame = r_framecount; if( !R_AddDSurfToDrawList( e, fog, shader, dist, order, portalSurface, drawSurf ) ) { return; } } // keep track of the actual vbo chunk we need to render R_AddVBOSlice( drawSurf - r_worldbrushmodel->drawSurfaces, surf->mesh->numVerts, surf->mesh->numElems, surf->firstDrawSurfVert, surf->firstDrawSurfElem ); // dynamic lights that affect the surface if( dlightBits && R_SurfPotentiallyLit( surf ) ) { // ignore dlights that have already been marked as affectors if( drawSurf->dlightFrame == rf.sceneFrameCount ) { drawSurf->dlightBits |= dlightBits; } else { drawSurf->dlightBits = dlightBits; drawSurf->dlightFrame = rf.sceneFrameCount; } } // shadows that are projected onto the surface if( shadowBits && R_SurfPotentiallyShadowed( surf ) ) { // ignore shadows that have already been marked as affectors if( drawSurf->shadowFrame == rf.sceneFrameCount ) { drawSurf->shadowBits |= shadowBits; } else { drawSurf->shadowBits = shadowBits; drawSurf->shadowFrame = rf.sceneFrameCount; } } c_brush_polys++; rn.numVisSurfaces++; }