int angleSteps, elevationSteps;
float angle, elevation;
float angleStep, elevationStep;
- float step, start;
sun_t sun;
if( value <= 0.0f || iterations < 2 )
return;
- /* calculate some stuff */
- step = 2.0f / (iterations - 1);
- start = -1.0f;
-
/* basic sun setup */
VectorCopy( color, sun.color );
sun.deviance = 0.0f;
float angle;
float add;
float dist;
- float addDeluxe = 0.0f, addDeluxeBounceScale = 0.25f;\r
- qboolean angledDeluxe = qfalse;\r
+ float addDeluxe = 0.0f, addDeluxeBounceScale = 0.25f;
+ qboolean angledDeluxe = qtrue;
float colorBrightness;
+ qboolean doAddDeluxe = qtrue;
/* get light */
light = trace->light;
/* clear color */
+ trace->forceSubsampling = 0.0f; /* to make sure */
VectorClear( trace->color );
VectorClear( trace->colorNoShadow );
- VectorClear( trace->directionContribution );\r
-\r
+ VectorClear( trace->directionContribution );
+
colorBrightness = RGBTOGRAY( light->color ) * ( 1.0f/255.0f );
/* ydnar: early out */
angle = DotProduct( trace->normal, trace->direction );
/* twosided lighting */
- if( trace->twoSided )
- angle = fabs( angle );
+ if( trace->twoSided && angle < 0 )
+ {
+ angle = -angle;
+
+ /* no deluxemap contribution from "other side" light */
+ doAddDeluxe = qfalse;
+ }
/* attenuate */
angle *= -DotProduct( light->normal, trace->direction );
return 0;
else if( angle < 0.0f &&
(trace->twoSided || (light->flags & LIGHT_TWOSIDED)) )
+ {
angle = -angle;
+ /* no deluxemap contribution from "other side" light */
+ doAddDeluxe = qfalse;
+ }
+
/* clamp the distance to prevent super hot spots */
dist = sqrt(dist * dist + light->extraDist * light->extraDist);
if( dist < 16.0f )
add = light->photons / (dist * dist) * angle;
- if( deluxemap )\r
- {\r
- if( angledDeluxe )\r
- addDeluxe = light->photons / (dist * dist) * angle;\r
- else\r
- addDeluxe = light->photons / (dist * dist);\r
+ if( deluxemap )
+ {
+ if( angledDeluxe )
+ addDeluxe = light->photons / (dist * dist) * angle;
+ else
+ addDeluxe = light->photons / (dist * dist);
}
}
else
dist = SetupTrace( trace );
if( dist >= light->envelope )
return 0;
+
+ /* no deluxemap contribution from "other side" light */
+ doAddDeluxe = qfalse;
}
else
return 0;
}
+
+ /* also don't deluxe if the direction is on the wrong side */
+ if(DotProduct(trace->normal, trace->direction) < 0)
+ {
+ /* no deluxemap contribution from "other side" light */
+ doAddDeluxe = qfalse;
+ }
/* ydnar: moved to here */
add = factor * light->add;
- if( deluxemap )\r
+ if( deluxemap )
addDeluxe = add;
}
}
float dot = DotProduct( trace->normal, trace->direction );
/* twosided lighting */
- if( trace->twoSided )
- dot = fabs( dot );
+ if( trace->twoSided && dot < 0 )
+ {
+ dot = -dot;
+
+ /* no deluxemap contribution from "other side" light */
+ doAddDeluxe = qfalse;
+ }
/* jal: optional half Lambert attenuation (http://developer.valvesoftware.com/wiki/Half_Lambert) */
if( lightAngleHL )
if( add < 0.0f )
add = 0.0f;
- if( deluxemap )\r
- {\r
- if( angledDeluxe )\r
- addDeluxe = angle * light->photons * linearScale - (dist * light->fade);\r
- else\r
- addDeluxe = light->photons * linearScale - (dist * light->fade);\r
-\r
- if( addDeluxe < 0.0f )\r
- addDeluxe = 0.0f;\r
+ 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;
- if( add < 0.0f )\r
- add = 0.0f;\r
-\r
- if( deluxemap )\r
- {\r
- if( angledDeluxe )\r
- addDeluxe = (light->photons / (dist * dist)) * angle;\r
- else\r
- addDeluxe = (light->photons / (dist * dist));\r
- }\r
-\r
- if( addDeluxe < 0.0f )\r
+ 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;
}
if( sampleRadius > (radiusAtDist - 32.0f) )
{
add *= ((radiusAtDist - sampleRadius) / 32.0f);
- if( add < 0.0f )\r
- add = 0.0f;\r
-\r
- addDeluxe *= ((radiusAtDist - sampleRadius) / 32.0f);\r
-\r
- if( addDeluxe < 0.0f )\r
+ if( add < 0.0f )
+ add = 0.0f;
+
+ addDeluxe *= ((radiusAtDist - sampleRadius) / 32.0f);
+
+ if( addDeluxe < 0.0f )
addDeluxe = 0.0f;
}
}
float dot = DotProduct( trace->normal, trace->direction );
/* twosided lighting */
- if( trace->twoSided )
- dot = fabs( dot );
+ if( trace->twoSided && dot < 0 )
+ {
+ dot = -dot;
+
+ /* no deluxemap contribution from "other side" light */
+ doAddDeluxe = qfalse;
+ }
/* jal: optional half Lambert attenuation (http://developer.valvesoftware.com/wiki/Half_Lambert) */
if( lightAngleHL )
/* attenuate */
add = light->photons * angle;
- if( deluxemap )\r
- {\r
- if( angledDeluxe )\r
- addDeluxe = light->photons * angle;\r
- else\r
- addDeluxe = light->photons;\r
-\r
- if( addDeluxe < 0.0f )\r
- addDeluxe = 0.0f;\r
+ if( deluxemap )
+ {
+ if( angledDeluxe )
+ addDeluxe = light->photons * angle;
+ else
+ addDeluxe = light->photons;
+
+ if( addDeluxe < 0.0f )
+ addDeluxe = 0.0f;
}
if( add <= 0.0f )
/* VorteX: set noShadow color */
VectorScale(light->color, add, trace->colorNoShadow);
- addDeluxe *= colorBrightness;\r
-\r
- if( bouncing )\r
- {\r
- addDeluxe *= addDeluxeBounceScale;\r
- if( addDeluxe < 0.00390625f )\r
- addDeluxe = 0.00390625f;\r
- }\r
-\r
+ addDeluxe *= colorBrightness;
+
+ if( bouncing )
+ {
+ addDeluxe *= addDeluxeBounceScale;
+ if( addDeluxe < 0.00390625f )
+ addDeluxe = 0.00390625f;
+ }
+
VectorScale( trace->direction, addDeluxe, trace->directionContribution );
/* setup trace */
{
/* trace */
TraceLine( trace );
+ trace->forceSubsampling *= add;
if( !(trace->compileFlags & C_SKY) || trace->opaque )
{
VectorClear( trace->color );
/* return to sender */
return 1;
}
+ else
+ Error("Light of undefined type!");
/* VorteX: set noShadow color */
VectorScale(light->color, add, trace->colorNoShadow);
if( add <= 0.0f || (add <= light->falloffTolerance && (light->flags & LIGHT_FAST_ACTUAL)) )
return 0;
- addDeluxe *= colorBrightness;\r
-\r
- /* hack land: scale down the radiosity contribution to light directionality.\r
- Deluxemaps fusion many light directions into one. In a rtl process all lights\r
- would contribute individually to the bump map, so several light sources together\r
- would make it more directional (example: a yellow and red lights received from\r
- opposing sides would light one side in red and the other in blue, adding\r
- the effect of 2 directions applied. In the deluxemapping case, this 2 lights would\r
- neutralize each other making it look like having no direction.\r
- Same thing happens with radiosity. In deluxemapping case the radiosity contribution\r
- is modifying the direction applied from directional lights, making it go closer and closer\r
- to the surface normal the bigger is the amount of radiosity received.\r
- So, for preserving the directional lights contributions, we scale down the radiosity\r
- contribution. It's a hack, but there's a reason behind it */\r
- if( bouncing )\r
- {\r
- addDeluxe *= addDeluxeBounceScale;\r
- if( addDeluxe < 0.00390625f )\r
- addDeluxe = 0.00390625f;\r
- }\r
-\r
- VectorScale( trace->direction, addDeluxe, trace->directionContribution );
+ 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;
+ /* better NOT increase it beyond the original value
+ if( addDeluxe < 0.00390625f )
+ addDeluxe = 0.00390625f;
+ */
+ }
+
+ if(doAddDeluxe)
+ {
+ VectorScale( trace->direction, addDeluxe, trace->directionContribution );
+ }
/* setup trace */
trace->testAll = qfalse;
/* raytrace */
TraceLine( trace );
+ trace->forceSubsampling *= add;
if( trace->passSolid || trace->opaque )
{
VectorClear( trace->color );
- VectorClear( trace->directionContribution );\r
+ VectorClear( trace->directionContribution );
return -1;
}
/////// Floodlighting for point //////////////////
//do our floodlight ambient occlusion loop, and add a single contribution based on the brightest dir
- if( floodlighty )\r
- {\r
- int k;\r
- float addSize, f;\r
- vec3_t dir = { 0, 0, 1 };\r
- float ambientFrac = 0.25f;\r
-\r
- trace.testOcclusion = qtrue;\r
- trace.forceSunlight = qfalse;\r
- trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;\r
- trace.testAll = qtrue;\r
-\r
- for( k = 0; k < 2; k++ )\r
- {\r
- if( k == 0 ) // upper hemisphere\r
- {\r
- trace.normal[0] = 0;\r
- trace.normal[1] = 0;\r
- trace.normal[2] = 1;\r
- }\r
- else //lower hemisphere\r
- {\r
- trace.normal[0] = 0;\r
- trace.normal[1] = 0;\r
- trace.normal[2] = -1;\r
- }\r
-\r
- f = FloodLightForSample( &trace, floodlightDistance, floodlight_lowquality );\r
-\r
- /* add a fraction as pure ambient, half as top-down direction */\r
- contributions[ numCon ].color[0]= floodlightRGB[0] * floodlightIntensity * f * ( 1.0f - ambientFrac );\r
- contributions[ numCon ].color[1]= floodlightRGB[1] * floodlightIntensity * f * ( 1.0f - ambientFrac );\r
- contributions[ numCon ].color[2]= floodlightRGB[2] * floodlightIntensity * f * ( 1.0f - ambientFrac );\r
-\r
- contributions[ numCon ].ambient[0]= floodlightRGB[0] * floodlightIntensity * f * ambientFrac;\r
- contributions[ numCon ].ambient[1]= floodlightRGB[1] * floodlightIntensity * f * ambientFrac;\r
- contributions[ numCon ].ambient[2]= floodlightRGB[2] * floodlightIntensity * f * ambientFrac;\r
-\r
- contributions[ numCon ].dir[0] = dir[0];\r
- contributions[ numCon ].dir[1] = dir[1];\r
- contributions[ numCon ].dir[2] = dir[2];\r
-\r
- contributions[ numCon ].style = 0;\r
-\r
- /* push average direction around */\r
- addSize = VectorLength( contributions[ numCon ].color );\r
- VectorMA( gp->dir, addSize, dir, gp->dir );\r
-\r
- numCon++;\r
- }\r
+ 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++;
+ }
}
/////////////////////
vec3_t color;
float f;
int b, bt;
- qboolean minVertex, minGrid, ps;
+ qboolean minVertex, minGrid;
const char *value;
char mapSource[ 1024 ];
const char *value;
int lightmapMergeSize = 0;
+ qboolean lightSamplesInsist = qfalse;
/* note it */
lightmapGamma = game->lightmapGamma;
Sys_Printf( " lightning gamma: %f\n", lightmapGamma );
+ lightmapsRGB = game->lightmapsRGB;
+ if(lightmapsRGB)
+ Sys_Printf( " lightmap colorspace: sRGB\n" );
+ else
+ Sys_Printf( " lightmap colorspace: linear\n" );
+
lightmapCompensate = game->lightmapCompensate;
Sys_Printf( " lightning compensation: %f\n", lightmapCompensate );
else if( !strcmp( argv[ i ], "-griddirectionality" ) )
{
f = atof( argv[ i + 1 ] );
- if(f < 0) f = 0;
- if(f > gridAmbientDirectionality) f = gridAmbientDirectionality;
+ if(f > 1) f = 1;
+ if(f < gridAmbientDirectionality) gridAmbientDirectionality = f;
Sys_Printf( "Grid directionality is %f\n", f );
- gridDirectionality *= f;
+ gridDirectionality = f;
i++;
}
else if( !strcmp( argv[ i ], "-gridambientdirectionality" ) )
{
f = atof( argv[ i + 1 ] );
- if(f > gridDirectionality) f = gridDirectionality;
- if(f > 1) f = 1;
+ if(f < -1) f = -1;
+ if(f > gridDirectionality) gridDirectionality = f;
Sys_Printf( "Grid ambient directionality is %f\n", f );
- gridAmbientDirectionality *= f;
+ gridAmbientDirectionality = f;
i++;
}
i++;
}
+ else if( !strcmp( argv[ i ], "-sRGB" ) )
+ {
+ lightmapsRGB = qtrue;
+ Sys_Printf( "Lighting is in sRGB\n" );
+ }
+
+ else if( !strcmp( argv[ i ], "-nosRGB" ) )
+ {
+ lightmapsRGB = qfalse;
+ Sys_Printf( "Lighting is linear\n" );
+ }
+
else if( !strcmp( argv[ i ], "-exposure" ) )
{
f = atof( argv[ i + 1 ] );
i++;
}
+ else if( !strcmp( argv[ i ], "-randomsamples" ) )
+ {
+ lightRandomSamples = qtrue;
+ Sys_Printf( "Random sampling enabled\n", lightRandomSamples );
+ }
+
else if( !strcmp( argv[ i ], "-samples" ) )
{
+ if(*argv[i+1] == '+')
+ lightSamplesInsist = qtrue;
+ else
+ lightSamplesInsist = qfalse;
lightSamples = atoi( argv[ i + 1 ] );
if( lightSamples < 1 )
lightSamples = 1;
i++;
}
+ else if( !strcmp( argv[ i ], "-samplessearchboxsize" ) )
+ {
+ lightSamplesSearchBoxSize = atoi( argv[ i + 1 ] );
+ if( lightSamplesSearchBoxSize <= 0 )
+ lightSamplesSearchBoxSize = 1;
+ if( lightSamplesSearchBoxSize > 4 )
+ lightSamplesSearchBoxSize = 4; /* more makes no sense */
+ else if( lightSamplesSearchBoxSize != 1 )
+ Sys_Printf( "Adaptive supersampling uses %f times the normal search box size\n", lightSamplesSearchBoxSize );
+ i++;
+ }
+
else if( !strcmp( argv[ i ], "-filter" ) )
{
filter = qtrue;
{
lightmapExtraVisClusterNudge = qtrue;
}
+ else if( !strcmp( argv[ i ], "-fill" ) )
+ {
+ lightmapFill = qtrue;
+ Sys_Printf( "Filling lightmap colors from surrounding pixels to improve JPEG compression\n" );
+ }
/* unhandled args */
else
{
}
+ /* fix up samples count */
+ if(lightRandomSamples)
+ {
+ if(!lightSamplesInsist)
+ {
+ /* approximately match -samples in quality */
+ switch(lightSamples)
+ {
+ /* somewhat okay */
+ case 1:
+ case 2:
+ lightSamples = 16;
+ Sys_Printf( "Adaptive supersampling preset enabled with %d random sample(s) per lightmap texel\n", lightSamples );
+ break;
+
+ /* good */
+ case 3:
+ lightSamples = 64;
+ Sys_Printf( "Adaptive supersampling preset enabled with %d random sample(s) per lightmap texel\n", lightSamples );
+ break;
+
+ /* perfect */
+ case 4:
+ lightSamples = 256;
+ Sys_Printf( "Adaptive supersampling preset enabled with %d random sample(s) per lightmap texel\n", lightSamples );
+ break;
+
+ default: break;
+ }
+ }
+ }
+
/* fix up lightmap search power */
if(lightmapMergeSize)
{
/* load map file */
value = ValueForKey( &entities[ 0 ], "_keepLights" );
if( value[ 0 ] != '1' )
- LoadMapFile( mapSource, qtrue );
+ LoadMapFile( mapSource, qtrue, qfalse );
/* set the entity/model origins and init yDrawVerts */
SetEntityOrigins();