/* * R_AddPortalSurface */ portalSurface_t *R_AddPortalSurface( const entity_t *ent, const shader_t *shader, void *drawSurf ) { portalSurface_t *portalSurface; bool depthPortal; if( !shader ) { return NULL; } depthPortal = !( shader->flags & ( SHADER_PORTAL_CAPTURE | SHADER_PORTAL_CAPTURE2 ) ); if( R_FASTSKY() && depthPortal ) { return NULL; } if( rn.numPortalSurfaces == MAX_PORTAL_SURFACES ) { // not enough space return NULL; } portalSurface = &rn.portalSurfaces[rn.numPortalSurfaces++]; memset( portalSurface, 0, sizeof( portalSurface_t ) ); portalSurface->entity = ent; portalSurface->shader = shader; portalSurface->skyPortal = NULL; ClearBounds( portalSurface->mins, portalSurface->maxs ); memset( portalSurface->texures, 0, sizeof( portalSurface->texures ) ); if( depthPortal ) { rn.numDepthPortalSurfaces++; } return portalSurface; }
/* * 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_AddPortalSurface */ portalSurface_t *R_AddPortalSurface( const entity_t *ent, const mesh_t *mesh, const vec3_t mins, const vec3_t maxs, const shader_t *shader ) { unsigned int i; float dist; cplane_t plane, untransformed_plane; vec3_t v[3]; portalSurface_t *portalSurface; if( !mesh ) { return NULL; } if( R_FASTSKY() && !( shader->flags & (SHADER_PORTAL_CAPTURE|SHADER_PORTAL_CAPTURE2) ) ) { // r_fastsky doesn't affect portalmaps return NULL; } for( i = 0; i < 3; i++ ) { VectorCopy( mesh->xyzArray[mesh->elems[i]], v[i] ); } PlaneFromPoints( v, &untransformed_plane ); untransformed_plane.dist += DotProduct( ent->origin, untransformed_plane.normal ); CategorizePlane( &untransformed_plane ); if( shader->flags & SHADER_AUTOSPRITE ) { vec3_t centre; // autosprites are quads, facing the viewer if( mesh->numVerts < 4 ) { return NULL; } // compute centre as average of 4 vertices VectorCopy( mesh->xyzArray[mesh->elems[3]], centre ); for( i = 0; i < 3; i++ ) VectorAdd( centre, v[i], centre ); VectorMA( ent->origin, 0.25, centre, centre ); VectorNegate( &rn.viewAxis[AXIS_FORWARD], plane.normal ); plane.dist = DotProduct( plane.normal, centre ); CategorizePlane( &plane ); } else { vec3_t temp; mat3_t entity_rotation; // regular surfaces if( !Matrix3_Compare( ent->axis, axis_identity ) ) { Matrix3_Transpose( ent->axis, entity_rotation ); for( i = 0; i < 3; i++ ) { VectorCopy( v[i], temp ); Matrix3_TransformVector( entity_rotation, temp, v[i] ); VectorMA( ent->origin, ent->scale, v[i], v[i] ); } PlaneFromPoints( v, &plane ); CategorizePlane( &plane ); } else { plane = untransformed_plane; } } if( ( dist = PlaneDiff( rn.viewOrigin, &plane ) ) <= BACKFACE_EPSILON ) { // behind the portal plane if( !( shader->flags & SHADER_PORTAL_CAPTURE2 ) ) { return NULL; } // we need to render the backplane view } // check if portal view is opaque due to alphagen portal if( shader->portalDistance && dist > shader->portalDistance ) { return NULL; } // find the matching portal plane for( i = 0; i < rn.numPortalSurfaces; i++ ) { portalSurface = &rn.portalSurfaces[i]; if( portalSurface->entity == ent && portalSurface->shader == shader && DotProduct( portalSurface->plane.normal, plane.normal ) > 0.99f && fabs( portalSurface->plane.dist - plane.dist ) < 0.1f ) { goto addsurface; } } if( i == MAX_PORTAL_SURFACES ) { // not enough space return NULL; } portalSurface = &rn.portalSurfaces[rn.numPortalSurfaces++]; portalSurface->entity = ent; portalSurface->plane = plane; portalSurface->shader = shader; portalSurface->untransformed_plane = untransformed_plane; ClearBounds( portalSurface->mins, portalSurface->maxs ); memset( portalSurface->texures, 0, sizeof( portalSurface->texures ) ); addsurface: AddPointToBounds( mins, portalSurface->mins, portalSurface->maxs ); AddPointToBounds( maxs, portalSurface->mins, portalSurface->maxs ); VectorAdd( portalSurface->mins, portalSurface->maxs, portalSurface->centre ); VectorScale( portalSurface->centre, 0.5, portalSurface->centre ); return portalSurface; }
/* * 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++; }