/* * R_MarkLeafSurfaces */ static void R_MarkLeafSurfaces( msurface_t **mark, unsigned int clipFlags, unsigned int dlightBits, unsigned int shadowBits ) { msurface_t *surf; unsigned int newDlightBits; unsigned int newShadowBits; drawSurfaceBSP_t *drawSurf; vec3_t centre; float distance; do { surf = *mark++; drawSurf = surf->drawSurf; if( R_CullSurface( rsc.worldent, surf, clipFlags ) ) { continue; } // avoid double-checking dlights that have already been added to drawSurf newDlightBits = dlightBits; if( drawSurf->dlightFrame == rsc.frameCount ) { newDlightBits &= ~drawSurf->dlightBits; } if( newDlightBits ) { newDlightBits = R_SurfaceDlightBits( surf, newDlightBits ); } newShadowBits = R_SurfaceShadowBits( surf, shadowBits ); if( surf->visFrame != rf.frameCount || newDlightBits || newShadowBits ) { VectorAdd( surf->mins, surf->maxs, centre ); VectorScale( centre, 0.5, centre ); distance = Distance( rn.refdef.vieworg, centre ); R_AddSurfaceToDrawList( rsc.worldent, surf, surf->fog, newDlightBits, newShadowBits, distance ); } surf->visFrame = rf.frameCount; } while( *mark ); }
/* * 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_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 ) { shader_t *shader; drawSurfaceBSP_t *drawSurf = surf->drawSurf; portalSurface_t *portalSurface = NULL; if( R_CullSurface( e, surf, clipFlags ) ) { return; } if( r_drawworld->integer == 2 ) { shader = rsh.envShader; } else { shader = surf->shader; if( shader->flags & SHADER_SKY ) { bool addSurf = true, addSlice = false; if( R_FASTSKY() ) { return; } if( R_ClipSkySurface( surf ) ) { if( rn.refdef.rdflags & RDF_SKYPORTALINVIEW ) { // for skyportals, generate portal surface and // also add BSP surface to skybox if it's fogged to render // the fog hull later portalSurface = R_AddSkyportalSurface( e, shader, drawSurf ); addSurf = portalSurface != NULL && surf->fog != NULL; addSlice = portalSurface != NULL; } if( addSurf ) { addSlice = R_AddSkySurfToDrawList( surf, portalSurface ); } if( addSlice ) { R_AddSurfaceVBOSlice( surf, 0 ); } } rn.numVisSurfaces++; return; } } if( drawSurf->visFrame != rf.frameCount ) { 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 ); } else { // just ignore the distance since we're drawing batched geometry anyway dist = 0; } drawSurf->visFrame = rf.frameCount; if( !R_AddSurfToDrawList( rn.meshlist, e, fog, shader, dist, 0, portalSurface, drawSurf ) ) { return; } if( portalSurface && !( shader->flags & (SHADER_PORTAL_CAPTURE|SHADER_PORTAL_CAPTURE2) ) ) { R_AddSurfToDrawList( rn.portalmasklist, e, NULL, rsh.skyShader, 0, 0, NULL, drawSurf ); } } // keep track of the actual vbo chunk we need to render R_AddSurfaceVBOSlice( surf, 0 ); // dynamic lights that affect the surface if( dlightBits ) { // 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_AddSurfaceVBOSlice( surf, rsh.worldBrushModel->numDrawSurfaces ); // 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_FindBmodelMirrors Check all bmodel surfaces and make personal mirror chain ================= */ void R_FindBmodelMirrors( cl_entity_t *e, qboolean static_entity ) { mextrasurf_t *extrasurf; vec3_t mins, maxs; msurface_t *psurf; model_t *clmodel; qboolean rotated; int i, clipFlags; clmodel = e->model; if( static_entity ) { Matrix4x4_LoadIdentity( RI.objectMatrix ); if( R_CullBox( clmodel->mins, clmodel->maxs, RI.clipFlags )) return; VectorCopy( RI.cullorigin, tr.modelorg ); clipFlags = RI.clipFlags; } else { if( !VectorIsNull( e->angles )) { for( i = 0; i < 3; i++ ) { mins[i] = e->origin[i] - clmodel->radius; maxs[i] = e->origin[i] + clmodel->radius; } rotated = true; } else { VectorAdd( e->origin, clmodel->mins, mins ); VectorAdd( e->origin, clmodel->maxs, maxs ); rotated = false; } if( R_CullBox( mins, maxs, RI.clipFlags )) return; if( !VectorIsNull( e->origin ) || !VectorIsNull( e->angles )) { if( rotated ) Matrix4x4_CreateFromEntity( RI.objectMatrix, e->angles, e->origin, 1.0f ); else Matrix4x4_CreateFromEntity( RI.objectMatrix, vec3_origin, e->origin, 1.0f ); } else Matrix4x4_LoadIdentity( RI.objectMatrix ); e->visframe = tr.framecount; // visible if( rotated ) Matrix4x4_VectorITransform( RI.objectMatrix, RI.cullorigin, tr.modelorg ); else VectorSubtract( RI.cullorigin, e->origin, tr.modelorg ); clipFlags = 0; } psurf = &clmodel->surfaces[clmodel->firstmodelsurface]; for( i = 0; i < clmodel->nummodelsurfaces; i++, psurf++ ) { if(!( psurf->flags & SURF_REFLECT )) continue; if( R_CullSurface( psurf, clipFlags )) continue; extrasurf = SURF_INFO( psurf, RI.currentmodel ); extrasurf->mirrorchain = tr.mirror_entities[tr.num_mirror_entities].chain; tr.mirror_entities[tr.num_mirror_entities].chain = extrasurf; } // store new mirror entity if( !static_entity && tr.mirror_entities[tr.num_mirror_entities].chain != NULL ) { tr.mirror_entities[tr.num_mirror_entities].ent = RI.currententity; tr.num_mirror_entities++; } }
/* ================ R_RecursiveMirrorNode ================ */ void R_RecursiveMirrorNode( mnode_t *node, uint clipflags ) { mextrasurf_t *extrasurf; const mplane_t *clipplane; int i, clipped; msurface_t *surf, **mark; mleaf_t *pleaf; int c, side; float dot; if( node->contents == CONTENTS_SOLID ) return; // hit a solid leaf if( node->visframe != tr.visframecount ) return; if( clipflags ) { for( i = 0, clipplane = RI.frustum; i < 6; i++, clipplane++ ) { if(!( clipflags & ( 1<<i ))) continue; clipped = BoxOnPlaneSide( node->minmaxs, node->minmaxs + 3, clipplane ); if( clipped == 2 ) return; if( clipped == 1 ) clipflags &= ~(1<<i); } } // if a leaf node, draw stuff if( node->contents < 0 ) { pleaf = (mleaf_t *)node; mark = pleaf->firstmarksurface; c = pleaf->nummarksurfaces; if( c ) { do { (*mark)->visframe = tr.framecount; mark++; } while( --c ); } return; } // node is just a decision point, so go down the apropriate sides // find which side of the node we are on dot = PlaneDiff( tr.modelorg, node->plane ); side = (dot >= 0) ? 0 : 1; // recurse down the children, front side first R_RecursiveMirrorNode( node->children[side], clipflags ); // draw stuff for( c = node->numsurfaces, surf = cl.worldmodel->surfaces + node->firstsurface; c; c--, surf++ ) { if(!( surf->flags & SURF_REFLECT )) continue; if( R_CullSurface( surf, clipflags )) continue; extrasurf = SURF_INFO( surf, RI.currentmodel ); extrasurf->mirrorchain = tr.mirror_entities[0].chain; tr.mirror_entities[0].chain = extrasurf; } // recurse down the back side R_RecursiveMirrorNode( node->children[!side], clipflags ); }
/* * 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++; }
/* * 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; if( R_CullSurface( e, surf, 0 ) ) { continue; } surfDlightBits = R_SurfPotentiallyLit( surf ) ? dlightBits : 0; surfShadowBits = R_SurfPotentiallyShadowed( surf ) ? shadowBits : 0; R_AddSurfaceToDrawList( e, surf, fog, surfDlightBits, surfShadowBits, distance ); } } return true; }