]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/light.c
add also a -nosRGB option to turn sRGB off
[xonotic/netradiant.git] / tools / quake3 / q3map2 / light.c
index dee882eed1402ed1248a80250719d7d610aa83c9..b6dcb1224e1c14589c00f554da66e84353d1f840 100644 (file)
@@ -148,7 +148,6 @@ static void CreateSkyLights( vec3_t color, float value, int iterations, float fi
        int                     angleSteps, elevationSteps;
        float           angle, elevation;
        float           angleStep, elevationStep;
-       float           step, start;
        sun_t           sun;
        
        
@@ -156,10 +155,6 @@ static void CreateSkyLights( vec3_t color, float value, int iterations, float fi
        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;
@@ -749,18 +744,20 @@ int LightContributionToSample( trace_t *trace )
        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 */
@@ -820,8 +817,13 @@ int LightContributionToSample( trace_t *trace )
                        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 );
@@ -829,8 +831,13 @@ int LightContributionToSample( trace_t *trace )
                                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 )
@@ -838,12 +845,12 @@ int LightContributionToSample( trace_t *trace )
 
                        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
@@ -864,15 +871,25 @@ int LightContributionToSample( trace_t *trace )
                                        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;
                }
        }
@@ -898,8 +915,13 @@ int LightContributionToSample( trace_t *trace )
                        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 )
@@ -933,32 +955,32 @@ int LightContributionToSample( trace_t *trace )
                        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;
                }
                
@@ -985,12 +1007,12 @@ int LightContributionToSample( trace_t *trace )
                        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;
                        }
                }
@@ -1010,8 +1032,13 @@ int LightContributionToSample( trace_t *trace )
                        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 )
@@ -1034,15 +1061,15 @@ int LightContributionToSample( trace_t *trace )
                /* 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 )
@@ -1051,15 +1078,15 @@ int LightContributionToSample( trace_t *trace )
                /* 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 */
@@ -1071,6 +1098,7 @@ int LightContributionToSample( trace_t *trace )
                {
                        /* trace */
                        TraceLine( trace );
+                       trace->forceSubsampling *= add;
                        if( !(trace->compileFlags & C_SKY) || trace->opaque )
                        {
                                VectorClear( trace->color );
@@ -1083,6 +1111,8 @@ int LightContributionToSample( trace_t *trace )
                /* return to sender */
                return 1;
        }
+       else
+               Error("Light of undefined type!");
 
        /* VorteX: set noShadow color */
        VectorScale(light->color, add, trace->colorNoShadow);
@@ -1091,28 +1121,33 @@ int LightContributionToSample( trace_t *trace )
        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;
@@ -1120,10 +1155,11 @@ int LightContributionToSample( trace_t *trace )
        
        /* raytrace */
        TraceLine( trace );
+       trace->forceSubsampling *= add;
        if( trace->passSolid || trace->opaque )
        {
                VectorClear( trace->color );
-               VectorClear( trace->directionContribution );\r
+               VectorClear( trace->directionContribution );
 
                return -1;
        }
@@ -1535,56 +1571,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 )\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++;
+               }
        }
        /////////////////////
 
@@ -1791,7 +1827,7 @@ void LightWorld( void )
        vec3_t          color;
        float           f;
        int                     b, bt;
-       qboolean        minVertex, minGrid, ps;
+       qboolean        minVertex, minGrid;
        const char      *value;
        
 
@@ -2009,6 +2045,7 @@ int LightMain( int argc, char **argv )
        char            mapSource[ 1024 ];
        const char      *value;
        int lightmapMergeSize = 0;
+       qboolean        lightSamplesInsist = qfalse;
        
        
        /* note it */
@@ -2028,6 +2065,12 @@ int LightMain( int argc, char **argv )
        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 );
 
@@ -2142,20 +2185,20 @@ int LightMain( int argc, char **argv )
                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++;
                }
                
@@ -2167,6 +2210,18 @@ int LightMain( int argc, char **argv )
                        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 ] );
@@ -2206,8 +2261,18 @@ int LightMain( int argc, char **argv )
                        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;
@@ -2216,6 +2281,18 @@ int LightMain( int argc, char **argv )
                        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;
@@ -2690,6 +2767,11 @@ int LightMain( int argc, char **argv )
                {
                        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
                {
@@ -2698,6 +2780,38 @@ int LightMain( int argc, char **argv )
 
        }
 
+       /* 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)
        {
@@ -2741,7 +2855,7 @@ int LightMain( int argc, char **argv )
        /* 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();