void ComputePerLeafAmbientLighting() { // Figure out which lights should go in the per-leaf ambient cubes. int nInAmbientCube = 0; int nSurfaceLights = 0; for ( int i=0; i < *pNumworldlights; i++ ) { dworldlight_t *wl = &dworldlights[i]; if ( IsLeafAmbientSurfaceLight( wl ) ) wl->flags |= DWL_FLAGS_INAMBIENTCUBE; else wl->flags &= ~DWL_FLAGS_INAMBIENTCUBE; if ( wl->type == emit_surface ) ++nSurfaceLights; if ( wl->flags & DWL_FLAGS_INAMBIENTCUBE ) ++nInAmbientCube; } Msg( "%d of %d (%d%% of) surface lights went in leaf ambient cubes.\n", nInAmbientCube, nSurfaceLights, nSurfaceLights ? ((nInAmbientCube*100) / nSurfaceLights) : 0 ); g_pLeafAmbientLighting->SetCount( numleafs ); StartPacifier( "ComputePerLeafAmbientLighting: " ); for ( int leafID = 0; leafID < numleafs; leafID++ ) { dleaf_t *pLeaf = &dleafs[leafID]; Vector cube[6]; Vector center = ( Vector( pLeaf->mins[0], pLeaf->mins[1], pLeaf->mins[2] ) + Vector( pLeaf->maxs[0], pLeaf->maxs[1], pLeaf->maxs[2] ) ) * 0.5f; #if MAKE_LIGHT_BELOW_WATER_MATCH_LIGHT_ABOVE_WATER if (pLeaf->contents & CONTENTS_WATER) { center.z=pLeaf->maxs[2]+1; int above_leaf=PointLeafnum( center); dleaf_t *pLeaf = &dleafs[above_leaf]; center = ( Vector( pLeaf->mins[0], pLeaf->mins[1], pLeaf->mins[2] ) + Vector( pLeaf->maxs[0], pLeaf->maxs[1], pLeaf->maxs[2] ) ) * 0.5f; } #endif ComputeAmbientFromSphericalSamples( center, cube ); for ( int i = 0; i < 6; i++ ) { VectorToColorRGBExp32( cube[i], (*g_pLeafAmbientLighting)[leafID].m_Color[i] ); } UpdatePacifier( (float)leafID / numleafs ); } EndPacifier( true ); }
void ComputeAmbientForLeaf( int iThread, int leafID, CUtlVector<ambientsample_t> &list ) { CUtlVector<dplane_t> leafPlanes; CLeafSampler sampler( iThread ); GetLeafBoundaryPlanes( leafPlanes, leafID ); list.RemoveAll(); // this heuristic tries to generate at least one sample per volume (chosen to be similar to the size of a player) in the space int xSize = (dleafs[leafID].maxs[0] - dleafs[leafID].mins[0]) / 32; int ySize = (dleafs[leafID].maxs[1] - dleafs[leafID].mins[1]) / 32; int zSize = (dleafs[leafID].maxs[2] - dleafs[leafID].mins[2]) / 64; xSize = max(xSize,1); ySize = max(xSize,1); zSize = max(xSize,1); // generate update 128 candidate samples, always at least one sample int volumeCount = xSize * ySize * zSize; if ( g_bFastAmbient ) { // save compute time, only do one sample volumeCount = 1; } int sampleCount = clamp( volumeCount, 1, 128 ); if ( dleafs[leafID].contents & CONTENTS_SOLID ) { // don't generate any samples in solid leaves // NOTE: We copy the nearest non-solid leaf sample pointers into this leaf at the end return; } Vector cube[6]; for ( int i = 0; i < sampleCount; i++ ) { // compute each candidate sample and add to the list Vector samplePosition; sampler.GenerateLeafSamplePosition( leafID, leafPlanes, samplePosition ); ComputeAmbientFromSphericalSamples( iThread, samplePosition, cube ); // note this will remove the least valuable sample once the limit is reached AddSampleToList( list, samplePosition, cube ); } // remove any samples that can be reconstructed with the remaining data CompressAmbientSampleList( list ); }