/* * R_AddSkyportalSurface */ portalSurface_t *R_AddSkyportalSurface( const entity_t *ent, const shader_t *shader, void *drawSurf ) { portalSurface_t *portalSurface; if( rn.skyportalSurface ) { portalSurface = rn.skyportalSurface; } else if( rn.numPortalSurfaces == MAX_PORTAL_SURFACES ) { // not enough space return NULL; } else { portalSurface = &rn.portalSurfaces[rn.numPortalSurfaces++]; memset( portalSurface, 0, sizeof( *portalSurface ) ); rn.skyportalSurface = portalSurface; rn.numDepthPortalSurfaces++; } R_AddSurfToDrawList( rn.portalmasklist, ent, NULL, rsh.skyShader, 0, 0, NULL, drawSurf ); portalSurface->entity = ent; portalSurface->shader = shader; portalSurface->skyPortal = &rn.refdef.skyportal; return rn.skyportalSurface; }
/* * R_RenderDebugSurface */ static void R_RenderDebugSurface( const refdef_t *fd ) { rtrace_t tr; vec3_t forward; vec3_t start, end; msurface_t *surf; if( fd->rdflags & RDF_NOWORLDMODEL ) return; if( r_speeds->integer != 4 && r_speeds->integer != 5 ) return; VectorCopy( &fd->viewaxis[AXIS_FORWARD], forward ); VectorCopy( fd->vieworg, start ); VectorMA( start, 4096, forward, end ); surf = R_TraceLine( &tr, start, end, 0 ); if( surf && surf->drawSurf && !r_showtris->integer ) { R_ClearDrawList( rn.meshlist ); R_ClearDrawList( rn.portalmasklist ); if( !R_AddSurfToDrawList( rn.meshlist, R_NUM2ENT(tr.ent), NULL, surf->shader, 0, 0, NULL, surf->drawSurf ) ) { return; } if( rn.refdef.rdflags & RDF_FLIPPED ) RB_FlipFrontFace(); rsc.debugSurface = surf; if( r_speeds->integer == 5 ) { // VBO debug mode R_AddVBOSlice( surf->drawSurf - rsh.worldBrushModel->drawSurfaces, surf->drawSurf->numVerts, surf->drawSurf->numElems, 0, 0 ); } else { // classic mode (showtris for individual surface) R_AddVBOSlice( surf->drawSurf - rsh.worldBrushModel->drawSurfaces, surf->mesh->numVerts, surf->mesh->numElems, surf->firstDrawSurfVert, surf->firstDrawSurfElem ); } R_DrawOutlinedSurfaces( rn.meshlist ); if( rn.refdef.rdflags & RDF_FLIPPED ) RB_FlipFrontFace(); } }
/* * 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_AddSkySurfToDrawList */ void *R_AddSkySurfToDrawList( drawList_t *list, const shader_t *shader,const portalSurface_t *portalSurf, drawSurfaceSky_t *drawSurf ) { return R_AddSurfToDrawList( rn.meshlist, rsc.skyent, NULL, shader, 0, 0, portalSurf, drawSurf ); }
/* * R_AddAliasModelToDrawList * * Returns true if the entity is added to draw list */ bool R_AddAliasModelToDrawList( const entity_t *e ) { int i, j; const model_t *mod; const maliasmodel_t *aliasmodel; const mfog_t *fog; const shader_t *shader; const maliasmesh_t *mesh; vec3_t mins, maxs; float radius; float distance; int clipped; mod = R_AliasModelLOD( e ); if( !( aliasmodel = ( ( const maliasmodel_t * )mod->extradata ) ) || !aliasmodel->nummeshes ) return false; radius = R_AliasModelLerpBBox( e, mod, mins, maxs ); clipped = R_CullModelEntity( e, mins, maxs, radius, true, aliasmodel->numtris > 100 ); if( clipped ) return false; // never render weapon models or non-occluders into shadowmaps if( rn.renderFlags & RF_SHADOWMAPVIEW ) { if( e->renderfx & RF_WEAPONMODEL ) { return true; } if( rsc.entShadowGroups[R_ENT2NUM(e)] != rn.shadowGroup->id ) { return true; } } // make sure weapon model is always closest to the viewer if( e->renderfx & RF_WEAPONMODEL ) { distance = 0; } else { distance = Distance( e->origin, rn.viewOrigin ) + 1; } fog = R_FogForSphere( e->origin, radius ); #if 0 if( !( e->flags & RF_WEAPONMODEL ) && fog ) { R_AliasModelLerpBBox( e, mod ); if( R_CompletelyFogged( fog, e->origin, radius ) ) return false; } #endif for( i = 0, mesh = aliasmodel->meshes; i < aliasmodel->nummeshes; i++, mesh++ ) { shader = NULL; if( e->customSkin ) { shader = R_FindShaderForSkinFile( e->customSkin, mesh->name ); } else if( e->customShader ) { shader = e->customShader; } else if( mesh->numskins ) { for( j = 0; j < mesh->numskins; j++ ) { shader = mesh->skins[j].shader; if( shader ) { R_AddSurfToDrawList( rn.meshlist, e, fog, shader, distance, 0, NULL, aliasmodel->drawSurfs + i ); } } continue; } if( shader ) { R_AddSurfToDrawList( rn.meshlist, e, fog, shader, distance, 0, NULL, aliasmodel->drawSurfs + i ); } } return true; }