X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=tools%2Fquake3%2Fq3map2%2Flight.c;h=977fa32f28fbbe4dae12893fec306c30fd81dacf;hb=4741e6535e6bbdf58ab856a3edd7f2b37761592b;hp=9f06cfd361e6955e61057dca3b81a58d1b6f7175;hpb=714c46381553bcc3d30f44e512fd9abce55314d0;p=xonotic%2Fnetradiant.git diff --git a/tools/quake3/q3map2/light.c b/tools/quake3/q3map2/light.c index 9f06cfd3..977fa32f 100644 --- a/tools/quake3/q3map2/light.c +++ b/tools/quake3/q3map2/light.c @@ -401,6 +401,10 @@ void CreateEntityLights( void ) else light->color[ 0 ] = light->color[ 1 ] = light->color[ 2 ] = 1.0f; + light->extraDist = FloatForKey( e, "_extradist" ); + if(light->extraDist == 0.0f) + light->extraDist = extraDist; + intensity = intensity * pointScale; light->photons = intensity; @@ -745,7 +749,9 @@ int LightContributionToSample( trace_t *trace ) float angle; float add; float dist; - + float addDeluxe = 0.0f, addDeluxeBounceScale = 0.25f; + qboolean angledDeluxe = qfalse; + float colorBrightness; /* get light */ light = trace->light; @@ -753,6 +759,9 @@ int LightContributionToSample( trace_t *trace ) /* clear color */ VectorClear( trace->color ); VectorClear( trace->colorNoShadow ); + VectorClear( trace->directionContribution ); + + colorBrightness = RGBTOGRAY( light->color ) * ( 1.0f/255.0f ); /* ydnar: early out */ if( !(light->flags & LIGHT_SURFACES) || light->envelope <= 0.0f ) @@ -792,7 +801,7 @@ int LightContributionToSample( trace_t *trace ) } /* nudge the point so that it is clearly forward of the light */ - /* so that surfaces meeting a light emiter don't get black edges */ + /* so that surfaces meeting a light emitter don't get black edges */ if( d > -8.0f && d < 8.0f ) VectorMA( trace->origin, (8.0f - d), light->normal, pushedOrigin ); else @@ -821,7 +830,21 @@ int LightContributionToSample( trace_t *trace ) else if( angle < 0.0f && (trace->twoSided || (light->flags & LIGHT_TWOSIDED)) ) angle = -angle; + + /* clamp the distance to prevent super hot spots */ + dist = sqrt(dist * dist + light->extraDist * light->extraDist); + if( dist < 16.0f ) + dist = 16.0f; + add = light->photons / (dist * dist) * angle; + + if( deluxemap ) + { + if( angledDeluxe ) + addDeluxe = light->photons / (dist * dist) * angle; + else + addDeluxe = light->photons / (dist * dist); + } } else { @@ -848,6 +871,9 @@ int LightContributionToSample( trace_t *trace ) /* ydnar: moved to here */ add = factor * light->add; + + if( deluxemap ) + addDeluxe = add; } } @@ -859,13 +885,40 @@ int LightContributionToSample( trace_t *trace ) dist = SetupTrace( trace ); if( dist >= light->envelope ) return 0; - + /* clamp the distance to prevent super hot spots */ + dist = sqrt(dist * dist + light->extraDist * light->extraDist); if( dist < 16.0f ) dist = 16.0f; - + /* angle attenuation */ - angle = (light->flags & LIGHT_ATTEN_ANGLE) ? DotProduct( trace->normal, trace->direction ) : 1.0f; + if( light->flags & LIGHT_ATTEN_ANGLE ) + { + /* standard Lambert attenuation */ + float dot = DotProduct( trace->normal, trace->direction ); + + /* twosided lighting */ + if( trace->twoSided ) + dot = fabs( dot ); + + /* jal: optional half Lambert attenuation (http://developer.valvesoftware.com/wiki/Half_Lambert) */ + if( lightAngleHL ) + { + if( dot > 0.001f ) // skip coplanar + { + if( dot > 1.0f ) dot = 1.0f; + dot = ( dot * 0.5f ) + 0.5f; + dot *= dot; + } + else + dot = 0; + } + + angle = dot; + } + else + angle = 1.0f; + if( light->angleScale != 0.0f ) { angle /= light->angleScale; @@ -873,19 +926,41 @@ int LightContributionToSample( trace_t *trace ) angle = 1.0f; } - /* twosided lighting */ - if( trace->twoSided ) - angle = fabs( angle ); - /* attenuate */ if( light->flags & LIGHT_ATTEN_LINEAR ) { add = angle * light->photons * linearScale - (dist * light->fade); if( add < 0.0f ) add = 0.0f; + + if( deluxemap ) + { + if( angledDeluxe ) + addDeluxe = angle * light->photons * linearScale - (dist * light->fade); + else + addDeluxe = light->photons * linearScale - (dist * light->fade); + + if( addDeluxe < 0.0f ) + addDeluxe = 0.0f; + } } else - add = light->photons / (dist * dist) * angle; + { + add = (light->photons / (dist * dist)) * angle; + if( add < 0.0f ) + add = 0.0f; + + if( deluxemap ) + { + if( angledDeluxe ) + addDeluxe = (light->photons / (dist * dist)) * angle; + else + addDeluxe = (light->photons / (dist * dist)); + } + + if( addDeluxe < 0.0f ) + addDeluxe = 0.0f; + } /* handle spotlights */ if( light->type == EMIT_SPOT ) @@ -908,7 +983,16 @@ int LightContributionToSample( trace_t *trace ) /* attenuate */ if( sampleRadius > (radiusAtDist - 32.0f) ) + { add *= ((radiusAtDist - sampleRadius) / 32.0f); + if( add < 0.0f ) + add = 0.0f; + + addDeluxe *= ((radiusAtDist - sampleRadius) / 32.0f); + + if( addDeluxe < 0.0f ) + addDeluxe = 0.0f; + } } } @@ -918,23 +1002,65 @@ int LightContributionToSample( trace_t *trace ) /* get origin and direction */ VectorAdd( trace->origin, light->origin, trace->end ); dist = SetupTrace( trace ); - + /* angle attenuation */ - angle = (light->flags & LIGHT_ATTEN_ANGLE) - ? DotProduct( trace->normal, trace->direction ) - : 1.0f; - - /* twosided lighting */ - if( trace->twoSided ) - angle = fabs( angle ); + if( light->flags & LIGHT_ATTEN_ANGLE ) + { + /* standard Lambert attenuation */ + float dot = DotProduct( trace->normal, trace->direction ); + + /* twosided lighting */ + if( trace->twoSided ) + dot = fabs( dot ); + + /* jal: optional half Lambert attenuation (http://developer.valvesoftware.com/wiki/Half_Lambert) */ + if( lightAngleHL ) + { + if( dot > 0.001f ) // skip coplanar + { + if( dot > 1.0f ) dot = 1.0f; + dot = ( dot * 0.5f ) + 0.5f; + dot *= dot; + } + else + dot = 0; + } + + angle = dot; + } + else + angle = 1.0f; /* attenuate */ add = light->photons * angle; + + if( deluxemap ) + { + if( angledDeluxe ) + addDeluxe = light->photons * angle; + else + addDeluxe = light->photons; + + if( addDeluxe < 0.0f ) + addDeluxe = 0.0f; + } + if( add <= 0.0f ) return 0; /* VorteX: set noShadow color */ VectorScale(light->color, add, trace->colorNoShadow); + + addDeluxe *= colorBrightness; + + if( bouncing ) + { + addDeluxe *= addDeluxeBounceScale; + if( addDeluxe < 0.00390625f ) + addDeluxe = 0.00390625f; + } + + VectorScale( trace->direction, addDeluxe, trace->directionContribution ); /* setup trace */ trace->testAll = qtrue; @@ -948,6 +1074,8 @@ int LightContributionToSample( trace_t *trace ) if( !(trace->compileFlags & C_SKY) || trace->opaque ) { VectorClear( trace->color ); + VectorClear( trace->directionContribution ); + return -1; } } @@ -962,6 +1090,29 @@ int LightContributionToSample( trace_t *trace ) /* ydnar: changed to a variable number */ if( add <= 0.0f || (add <= light->falloffTolerance && (light->flags & LIGHT_FAST_ACTUAL)) ) return 0; + + addDeluxe *= colorBrightness; + + /* hack land: scale down the radiosity contribution to light directionality. + Deluxemaps fusion many light directions into one. In a rtl process all lights + would contribute individually to the bump map, so several light sources together + would make it more directional (example: a yellow and red lights received from + opposing sides would light one side in red and the other in blue, adding + the effect of 2 directions applied. In the deluxemapping case, this 2 lights would + neutralize each other making it look like having no direction. + Same thing happens with radiosity. In deluxemapping case the radiosity contribution + is modifying the direction applied from directional lights, making it go closer and closer + to the surface normal the bigger is the amount of radiosity received. + So, for preserving the directional lights contributions, we scale down the radiosity + contribution. It's a hack, but there's a reason behind it */ + if( bouncing ) + { + addDeluxe *= addDeluxeBounceScale; + if( addDeluxe < 0.00390625f ) + addDeluxe = 0.00390625f; + } + + VectorScale( trace->direction, addDeluxe, trace->directionContribution ); /* setup trace */ trace->testAll = qfalse; @@ -972,6 +1123,8 @@ int LightContributionToSample( trace_t *trace ) if( trace->passSolid || trace->opaque ) { VectorClear( trace->color ); + VectorClear( trace->directionContribution ); + return -1; } @@ -1115,9 +1268,10 @@ int LightContributionToPoint( trace_t *trace ) if( light->type == EMIT_AREA && faster ) { /* clamp the distance to prevent super hot spots */ + dist = sqrt(dist * dist + light->extraDist * light->extraDist); if( dist < 16.0f ) dist = 16.0f; - + /* attenuate */ add = light->photons / (dist * dist); } @@ -1161,6 +1315,7 @@ int LightContributionToPoint( trace_t *trace ) else if( light->type == EMIT_POINT || light->type == EMIT_SPOT ) { /* clamp the distance to prevent super hot spots */ + dist = sqrt(dist * dist + light->extraDist * light->extraDist); if( dist < 16.0f ) dist = 16.0f; @@ -1266,21 +1421,21 @@ typedef struct { vec3_t dir; vec3_t color; + vec3_t ambient; int style; } contribution_t; void TraceGrid( int num ) { - int i, j, x, y, z, mod, step, numCon, numStyles; - float d; - vec3_t baseOrigin, cheapColor, color; + int i, j, x, y, z, mod, numCon, numStyles; + float d, step; + vec3_t baseOrigin, cheapColor, color, thisdir; rawGridPoint_t *gp; bspGridPoint_t *bgp; contribution_t contributions[ MAX_CONTRIBUTIONS ]; trace_t trace; - /* get grid points */ gp = &rawGridPoints[ num ]; bgp = &bspGridPoints[ num ]; @@ -1311,38 +1466,21 @@ void TraceGrid( int num ) { /* try to nudge the origin around to find a valid point */ VectorCopy( trace.origin, baseOrigin ); - for( step = 9; step <= 18; step += 9 ) + for( step = 0; (step += 0.005) <= 1.0; ) { - for( i = 0; i < 8; i++ ) - { - VectorCopy( baseOrigin, trace.origin ); - if( i & 1 ) - trace.origin[ 0 ] += step; - else - trace.origin[ 0 ] -= step; - - if( i & 2 ) - trace.origin[ 1 ] += step; - else - trace.origin[ 1 ] -= step; + VectorCopy( baseOrigin, trace.origin ); + trace.origin[ 0 ] += step * (Random() - 0.5) * gridSize[0]; + trace.origin[ 1 ] += step * (Random() - 0.5) * gridSize[1]; + trace.origin[ 2 ] += step * (Random() - 0.5) * gridSize[2]; - if( i & 4 ) - trace.origin[ 2 ] += step; - else - trace.origin[ 2 ] -= step; - - /* ydnar: changed to find cluster num */ - trace.cluster = ClusterForPointExt( trace.origin, VERTEX_EPSILON ); - if( trace.cluster >= 0 ) - break; - } - - if( i != 8 ) + /* ydnar: changed to find cluster num */ + trace.cluster = ClusterForPointExt( trace.origin, VERTEX_EPSILON ); + if( trace.cluster >= 0 ) break; } /* can't find a valid point at all */ - if( step > 18 ) + if( step > 1.0 ) return; } @@ -1377,6 +1515,7 @@ void TraceGrid( int num ) /* add a contribution */ VectorCopy( trace.color, contributions[ numCon ].color ); VectorCopy( trace.direction, contributions[ numCon ].dir ); + VectorClear( contributions[ numCon ].ambient ); contributions[ numCon ].style = trace.light->style; numCon++; @@ -1396,56 +1535,61 @@ void TraceGrid( int num ) /////// Floodlighting for point ////////////////// //do our floodlight ambient occlusion loop, and add a single contribution based on the brightest dir - if (floodlighty) - { - int q; - float addSize,f; - vec3_t col,dir; - col[0]=col[1]=col[2]=floodlightIntensity; - dir[0]=dir[1]=0; - dir[2]=1; - - trace.testOcclusion = qtrue; - trace.forceSunlight = qfalse; - trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS; - trace.testAll = qtrue; - - for (q=0;q<2;q++) - { - if (q==0) //upper hemisphere - { - trace.normal[0]=0; - trace.normal[1]=0; - trace.normal[2]=1; - } - else //lower hemisphere - { - trace.normal[0]=0; - trace.normal[1]=0; - trace.normal[2]=-1; - } - - f = FloodLightForSample(&trace, floodlightDistance, floodlight_lowquality); - - contributions[ numCon ].color[0]=col[0]*f; - contributions[ numCon ].color[1]=col[1]*f; - contributions[ numCon ].color[2]=col[2]*f; - - contributions[ numCon ].dir[0]=dir[0]; - contributions[ numCon ].dir[1]=dir[1]; - contributions[ numCon ].dir[2]=dir[2]; - - contributions[ numCon ].style = 0; - numCon++; - /* push average direction around */ - addSize = VectorLength( col ); - VectorMA( gp->dir, addSize, dir, gp->dir ); - } + if( floodlighty ) + { + int k; + float addSize, f; + vec3_t dir = { 0, 0, 1 }; + float ambientFrac = 0.25f; + + trace.testOcclusion = qtrue; + trace.forceSunlight = qfalse; + trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS; + trace.testAll = qtrue; + + for( k = 0; k < 2; k++ ) + { + if( k == 0 ) // upper hemisphere + { + trace.normal[0] = 0; + trace.normal[1] = 0; + trace.normal[2] = 1; + } + else //lower hemisphere + { + trace.normal[0] = 0; + trace.normal[1] = 0; + trace.normal[2] = -1; + } + + f = FloodLightForSample( &trace, floodlightDistance, floodlight_lowquality ); + + /* add a fraction as pure ambient, half as top-down direction */ + contributions[ numCon ].color[0]= floodlightRGB[0] * floodlightIntensity * f * ( 1.0f - ambientFrac ); + contributions[ numCon ].color[1]= floodlightRGB[1] * floodlightIntensity * f * ( 1.0f - ambientFrac ); + contributions[ numCon ].color[2]= floodlightRGB[2] * floodlightIntensity * f * ( 1.0f - ambientFrac ); + + contributions[ numCon ].ambient[0]= floodlightRGB[0] * floodlightIntensity * f * ambientFrac; + contributions[ numCon ].ambient[1]= floodlightRGB[1] * floodlightIntensity * f * ambientFrac; + contributions[ numCon ].ambient[2]= floodlightRGB[2] * floodlightIntensity * f * ambientFrac; + + contributions[ numCon ].dir[0] = dir[0]; + contributions[ numCon ].dir[1] = dir[1]; + contributions[ numCon ].dir[2] = dir[2]; + + contributions[ numCon ].style = 0; + + /* push average direction around */ + addSize = VectorLength( contributions[ numCon ].color ); + VectorMA( gp->dir, addSize, dir, gp->dir ); + + numCon++; + } } ///////////////////// /* normalize to get primary light direction */ - VectorNormalize( gp->dir, gp->dir ); + VectorNormalize( gp->dir, thisdir ); /* now that we have identified the primary light direction, go back and separate all the light into directed and ambient */ @@ -1454,7 +1598,7 @@ void TraceGrid( int num ) for( i = 0; i < numCon; i++ ) { /* get relative directed strength */ - d = DotProduct( contributions[ i ].dir, gp->dir ); + d = DotProduct( contributions[ i ].dir, thisdir ); /* we map 1 to gridDirectionality, and 0 to gridAmbientDirectionality */ d = gridAmbientDirectionality + d * (gridDirectionality - gridAmbientDirectionality); if( d < 0.0f ) @@ -1495,6 +1639,8 @@ void TraceGrid( int num ) d = 0.25f * (1.0f - d); VectorMA( gp->ambient[ j ], d, contributions[ i ].color, gp->ambient[ j ] ); + VectorAdd( gp->ambient[ j ], contributions[ i ].ambient, gp->ambient[ j ] ); + /* * div0: * the total light average = ambient value + 0.25 * sum of all directional values @@ -1540,8 +1686,7 @@ void TraceGrid( int num ) #endif /* store direction */ - if( !bouncing ) - NormalToLatLong( gp->dir, bgp->latLong ); + NormalToLatLong( thisdir, bgp->latLong ); } @@ -1646,7 +1791,7 @@ void LightWorld( void ) vec3_t color; float f; int b, bt; - qboolean minVertex, minGrid; + qboolean minVertex, minGrid, ps; const char *value; @@ -1720,7 +1865,9 @@ void LightWorld( void ) SetupEnvelopes( qtrue, fastgrid ); Sys_Printf( "--- TraceGrid ---\n" ); + inGrid = qtrue; RunThreadsOnIndividual( numRawGridPoints, qtrue, TraceGrid ); + inGrid = qfalse; Sys_Printf( "%d x %d x %d = %d grid\n", gridBounds[ 0 ], gridBounds[ 1 ], gridBounds[ 2 ], numBSPGridPoints ); @@ -1743,10 +1890,6 @@ void LightWorld( void ) if( dirty ) { Sys_Printf( "--- DirtyRawLightmap ---\n" ); - - - - RunThreadsOnIndividual( numRawLightmaps, qtrue, DirtyRawLightmap ); } @@ -1816,7 +1959,9 @@ void LightWorld( void ) gridBoundsCulled = 0; Sys_Printf( "--- BounceGrid ---\n" ); + inGrid = qtrue; RunThreadsOnIndividual( numRawGridPoints, qtrue, TraceGrid ); + inGrid = qfalse; Sys_FPrintf( SYS_VRB, "%9d grid points envelope culled\n", gridEnvelopeCulled ); Sys_FPrintf( SYS_VRB, "%9d grid points bounds culled\n", gridBoundsCulled ); } @@ -1895,6 +2040,10 @@ int LightMain( int argc, char **argv ) gridAmbientScale = game->gridAmbientScale; Sys_Printf( " lightgrid ambient scale: %f\n", gridAmbientScale ); + lightAngleHL = game->lightAngleHL; + if( lightAngleHL ) + Sys_Printf( " half lambert light angle attenuation enabled \n" ); + noStyles = game->noStyles; if (noStyles == qtrue) Sys_Printf( " shader lightstyles hack: disabled\n" ); @@ -2003,7 +2152,7 @@ int LightMain( int argc, char **argv ) else if( !strcmp( argv[ i ], "-gridambientdirectionality" ) ) { f = atof( argv[ i + 1 ] ); - if(f > gridDirectionality) f = gridDirectionality + if(f > gridDirectionality) f = gridDirectionality; if(f > 1) f = 1; Sys_Printf( "Grid ambient directionality is %f\n", f ); gridAmbientDirectionality *= f; @@ -2197,6 +2346,15 @@ int LightMain( int argc, char **argv ) wolfLight = qfalse; Sys_Printf( "Enabling Quake 3 lighting model (nonlinear default)\n" ); } + + else if( !strcmp( argv[ i ], "-extradist" ) ) + { + extraDist = atof( argv[ i + 1 ] ); + if( extraDist < 0 ) + extraDist = 0; + i++; + Sys_Printf( "Default extra radius set to %f units\n", extraDist ); + } else if( !strcmp( argv[ i ], "-sunonly" ) ) { @@ -2431,6 +2589,17 @@ int LightMain( int argc, char **argv ) loMem = qtrue; Sys_Printf( "Enabling low-memory (potentially slower) lighting mode\n" ); } + else if( !strcmp( argv[ i ], "-lightanglehl" ) ) + { + if( ( atoi( argv[ i + 1 ] ) != 0 ) != lightAngleHL ) + { + lightAngleHL = ( atoi( argv[ i + 1 ] ) != 0 ); + if( lightAngleHL ) + Sys_Printf( "Enabling half lambert light angle attenuation\n" ); + else + Sys_Printf( "Disabling half lambert light angle attenuation\n" ); + } + } else if( !strcmp( argv[ i ], "-nostyle" ) || !strcmp( argv[ i ], "-nostyles" ) ) { noStyles = qtrue;