X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=tools%2Fquake3%2Fq3map2%2Flight.c;h=977fa32f28fbbe4dae12893fec306c30fd81dacf;hb=4741e6535e6bbdf58ab856a3edd7f2b37761592b;hp=feb8ebc942db9c434cb80f5f222121a74ad48fc6;hpb=7bf5f3438d619eb8cafc380b82cd80e5a0c1f77e;p=xonotic%2Fnetradiant.git diff --git a/tools/quake3/q3map2/light.c b/tools/quake3/q3map2/light.c index feb8ebc9..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,6 +1421,7 @@ typedef struct { vec3_t dir; vec3_t color; + vec3_t ambient; int style; } contribution_t; @@ -1359,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++; @@ -1378,51 +1535,56 @@ 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++; + } } ///////////////////// @@ -1477,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 @@ -1726,10 +1890,6 @@ void LightWorld( void ) if( dirty ) { Sys_Printf( "--- DirtyRawLightmap ---\n" ); - - - - RunThreadsOnIndividual( numRawLightmaps, qtrue, DirtyRawLightmap ); } @@ -1880,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" ); @@ -2182,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" ) ) { @@ -2416,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;