diff --git a/utils/pxrad/ambientcube.cpp b/utils/pxrad/ambientcube.cpp index c71155d4..3b38c969 100644 --- a/utils/pxrad/ambientcube.cpp +++ b/utils/pxrad/ambientcube.cpp @@ -211,40 +211,11 @@ bool R_GetDirectLightFromSurface( dface_t *surf, const vec3_t point, lightpoint_ } - -//----------------------------------------------------------------------------- -// Finds ambient sky lights -//----------------------------------------------------------------------------- -static dworldlight_t *FindAmbientSkyLight( void ) -{ - static dworldlight_t *s_pCachedSkylight = NULL; - - // Don't keep searching for the same light. - if( !s_pCachedSkylight ) - { - // find any ambient lights - for( int iLight = 0; iLight < g_numworldlights; iLight++ ) - { - dworldlight_t *wl = &g_dworldlights[iLight]; - - if( wl->emittype == emit_skylight ) - { - s_pCachedSkylight = wl; - break; - } - } - } - - return s_pCachedSkylight; -} - - - //----------------------------------------------------------------------------- // Computes ambient lighting along a specified ray. // Ray represents a cone, tanTheta is the tan of the inner cone angle //----------------------------------------------------------------------------- -static void CalcRayAmbientLighting( int threadnum, const vec3_t vStart, const vec3_t vEnd, dworldlight_t *pSkyLight, float tanTheta, vec3_t radcolor ) +static void CalcRayAmbientLighting( int threadnum, const vec3_t vStart, const vec3_t vEnd, vec3_t radcolor ) { lightpoint_t info; vec3_t vDelta; @@ -291,7 +262,7 @@ static void CalcRayAmbientLighting( int threadnum, const vec3_t vStart, const ve //Msg( "solid angle %f\n", scaleAvg ); if( scaleAvg <= 0.0f ) return; - scaleAvg = 4.0f * M_PI / ((float)NUMVERTEXNORMALS * scaleAvg); //ratio of ray cone and face solid angles + scaleAvg = 4.0f * M_PI / ((float)g_numskynormals[g_lightprobelevel] * scaleAvg); //ratio of ray cone and face solid angles scaleAvg = bound( 0.0f, scaleAvg, 1.0f ); for (int i = 0; i < MAXLIGHTMAPS; i++ ) if( (info.styles[i] == LS_NORMAL)||(info.styles[i] == LS_SKY)||(info.styles[i] == g_skystyle)) //only sun, sky and default style @@ -305,39 +276,38 @@ static void CalcRayAmbientLighting( int threadnum, const vec3_t vStart, const ve static void ComputeAmbientFromSphericalSamples( int threadnum, const vec3_t p1, vec3_t lightBoxColor[6] ) { // Figure out the color that rays hit when shot out from this position. - float tanTheta = tan( VERTEXNORMAL_CONE_INNER_ANGLE ); - dworldlight_t *pSkyLight = FindAmbientSkyLight(); - vec3_t radcolor[NUMVERTEXNORMALS], p2; + vec3_t p2; + vec_t weight_sum[6]; - for( int i = 0; i < NUMVERTEXNORMALS; i++ ) + for ( int j = 0; j < 6; j++ ) { - VectorMA( p1, (65536.0f * 1.74f), g_anorms[i], p2 ); - - // Now that we've got a ray, see what surface we've hit - CalcRayAmbientLighting( threadnum, p1, p2, pSkyLight, tanTheta, radcolor[i] ); + VectorClear( lightBoxColor[j] ); + weight_sum[j] = 0.0f; } - // accumulate samples into radiant box - for ( int j = 0; j < 6; j++ ) + for( int i = 0; i < g_numskynormals[g_lightprobelevel]; i++ ) { - float t = 0.0f; + VectorMA( p1, (65536.0f * 1.74f), g_skynormals[g_lightprobelevel][i], p2 ); - VectorClear( lightBoxColor[j] ); + vec3_t temp_color; + CalcRayAmbientLighting( threadnum, p1, p2, temp_color); - for( int i = 0; i < NUMVERTEXNORMALS; i++ ) + for ( int j = 0; j < 6; j++ ) { - float c = DotProduct( g_anorms[i], g_BoxDirections[j] ); + float c = DotProduct( g_skynormals[g_lightprobelevel][i], g_BoxDirections[j] ) ; if( c > 0.0f ) { - VectorMA( lightBoxColor[j], c, radcolor[i], lightBoxColor[j] ); - t += c; + VectorMA( lightBoxColor[j], c , temp_color, lightBoxColor[j] ); + weight_sum[j] += c; } } - - VectorScale( lightBoxColor[j], ( 1.0 / t ), lightBoxColor[j] ); } + for ( int j = 0; j < 6; j++ ) + if( weight_sum[j] > 0.0f ) + VectorScale( lightBoxColor[j], 1.0f / weight_sum[j], lightBoxColor[j] ); + // Now add direct light from the emit_surface lights. These go in the ambient cube because // there are a ton of them and they are often so dim that they get filtered out by r_worldlightmin. AddEmitSurfaceLights( threadnum, p1, lightBoxColor ); @@ -535,10 +505,13 @@ void ComputeAmbientForLeaf( int threadnum, int leafID, ambientlocallist_t *list int ySize = (g_dleafs[leafID].maxs[1] - g_dleafs[leafID].mins[1]) / 64; int zSize = (g_dleafs[leafID].maxs[2] - g_dleafs[leafID].mins[2]) / 64; - xSize = Q_max( xSize, 1 ); - ySize = Q_max( ySize, 1 ); - zSize = Q_max( zSize, 1 ); - + int xMin = xSize > 1 ? 2 : 1; + int yMin = ySize > 1 ? 2 : 1; + int zMin = zSize > 1 ? 2 : 1; + + xSize = Q_max( xSize, xMin ); + ySize = Q_max( ySize, yMin ); + zSize = Q_max( zSize, zMin ); xSize = Q_min( xSize, MAX_LOCAL_SAMPLES ); ySize = Q_min( ySize, MAX_LOCAL_SAMPLES ); @@ -546,9 +519,9 @@ void ComputeAmbientForLeaf( int threadnum, int leafID, ambientlocallist_t *list while( xSize * ySize * zSize > MAX_LOCAL_SAMPLES ) //lazy way { - xSize = Q_max( xSize - 1, 1 ); - ySize = Q_max( ySize - 1, 1 ); - zSize = Q_max( zSize - 1, 1 ); + xSize = Q_max( xSize - 1, xMin ); + ySize = Q_max( ySize - 1, yMin ); + zSize = Q_max( zSize - 1, zMin ); } vec3_t cube[6]; diff --git a/utils/pxrad/qrad.cpp b/utils/pxrad/qrad.cpp index 7fc67099..fbf98625 100644 --- a/utils/pxrad/qrad.cpp +++ b/utils/pxrad/qrad.cpp @@ -74,6 +74,7 @@ bool g_studiolegacy = false; vec_t g_scale = DEFAULT_GLOBAL_SCALE; rgbdata_t *g_skytextures[6]; vec_t g_lightprobeepsilon = DEFAULT_LIGHTPROBE_EPSILON; +int g_lightprobelevel = 4; bool g_vertexblur = false; uint g_numstudiobounce = DEFAULT_STUDIO_BOUNCE; int g_studiogipasscounter = 0; @@ -2757,6 +2758,7 @@ static void PrintRadUsage( void ) Msg( " -worldspace : deluxe map in world space, not tangent space\n" ); Msg( " -studiolegacy : use legacy tree for studio models tracing instead of BVH\n" ); Msg( " -lightprobeepsilon #.#: set light probe importance threshold value. default is %f\n", DEFAULT_LIGHTPROBE_EPSILON ); + Msg( " -lightprobelevel #: set number of rays for light probes baking, final number is 4^n. default is 4\n" ); Msg( " -studiobounce #: set number of studio model radiosity bounces. default is %d\n", DEFAULT_STUDIO_BOUNCE ); Msg( " -vertexblur : blur per-vertex lighting\n" ); Msg( " -noemissive : do not add emissive textures to the lightmap\n" ); @@ -2912,7 +2914,12 @@ int main( int argc, char **argv ) { g_lightprobeepsilon = (float)atof( argv[i+1] ); i++; - } + } + else if( !Q_strcmp( argv[i], "-lightprobelevel" )) + { + g_lightprobelevel = atoi( argv[i+1] ); + i++; + } else if( !Q_strcmp( argv[i], "-studiobounce" )) { g_numstudiobounce = atoi( argv[i+1] ); @@ -3077,7 +3084,8 @@ int main( int argc, char **argv ) // keep it in acceptable range g_blur = bound( 1.0, g_blur, 8.0 ); g_gamma = bound( 0.3, g_gamma, 1.0 ); - g_skystyle = bound( 0, g_skystyle, 254 ); + g_skystyle = bound( 0, g_skystyle, 254 ); + g_lightprobelevel = bound( 1, g_lightprobelevel, SKYLEVELMAX ); RadWorld (); diff --git a/utils/pxrad/qrad.h b/utils/pxrad/qrad.h index 5776d499..9df8f299 100644 --- a/utils/pxrad/qrad.h +++ b/utils/pxrad/qrad.h @@ -429,6 +429,7 @@ extern bool g_studiolegacy; extern vec_t g_scale; extern rgbdata_t *g_skytextures[6]; extern vec_t g_lightprobeepsilon; +extern int g_lightprobelevel; extern directlight_t *g_skylights[256]; extern int g_numskylights; extern uint g_numstudiobounce;