]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/light_ydnar.c
slow down non-fast operation but make it more accurate by not using falloff tolerance...
[xonotic/netradiant.git] / tools / quake3 / q3map2 / light_ydnar.c
index b32c9a29c64ea8d628d16228e2222188ae4c9d42..12742f707cc439df86a172e6476d18979990c7d8 100644 (file)
@@ -74,7 +74,7 @@ void ColorToBytes( const float *color, byte *colorBytes, float scale )
                sample[ i ] = pow( sample[ i ] / 255.0f, gamma ) * 255.0f;
        }
 
-       if (lightmapExposure == 1)
+       if (lightmapExposure == 0)
        {
                /* clamp with color normalization */
                max = sample[ 0 ];
@@ -87,10 +87,6 @@ void ColorToBytes( const float *color, byte *colorBytes, float scale )
        }
        else
        {
-               if (lightmapExposure==0)
-               {
-                       lightmapExposure=1.0f;
-               }
                inv=1.f/lightmapExposure;
                //Exposure
 
@@ -120,6 +116,14 @@ void ColorToBytes( const float *color, byte *colorBytes, float scale )
        
        /* compensate for ingame overbrighting/bitshifting */
        VectorScale( sample, (1.0f / lightmapCompensate), sample );
+
+       /* sRGB lightmaps */
+       if(lightmapsRGB)
+       {
+               sample[0] = floor(Image_sRGBFloatFromLinearFloat(sample[0] * (1.0 / 255.0)) * 255.0 + 0.5);
+               sample[1] = floor(Image_sRGBFloatFromLinearFloat(sample[1] * (1.0 / 255.0)) * 255.0 + 0.5);
+               sample[2] = floor(Image_sRGBFloatFromLinearFloat(sample[2] * (1.0 / 255.0)) * 255.0 + 0.5);
+       }
        
        /* store it off */
        colorBytes[ 0 ] = sample[ 0 ];
@@ -1154,13 +1158,18 @@ void MapRawLightmap( int rawLightmapNum )
                                                if( MapQuad( lm, info, dv ) )
                                                        continue;
                                                
-                                               /* get drawverts and map first triangle */
-                                               MapTriangle( lm, info, dv, mapNonAxial );
-                                               
-                                               /* get drawverts and map second triangle */
-                                               dv[ 1 ] = &verts[ pw[ r + 2 ] ];
-                                               dv[ 2 ] = &verts[ pw[ r + 3 ] ];
-                                               MapTriangle( lm, info, dv, mapNonAxial );
+                                               for( mapNonAxial = 0; mapNonAxial < 2; mapNonAxial++ )
+                                               {
+                                                       /* get drawverts and map first triangle */
+                                                       dv[ 1 ] = &verts[ pw[ r + 1 ] ];
+                                                       dv[ 2 ] = &verts[ pw[ r + 2 ] ];
+                                                       MapTriangle( lm, info, dv, mapNonAxial );
+                                                       
+                                                       /* get drawverts and map second triangle */
+                                                       dv[ 1 ] = &verts[ pw[ r + 2 ] ];
+                                                       dv[ 2 ] = &verts[ pw[ r + 3 ] ];
+                                                       MapTriangle( lm, info, dv, mapNonAxial );
+                                               }
                                        }
                                }
                                
@@ -1471,7 +1480,7 @@ float DirtForSample( trace_t *trace )
                        
                        /* trace */
                        TraceLine( trace );
-                       if( trace->opaque )
+                       if( trace->opaque && !(trace->compileFlags & C_SKY) )
                        {
                                VectorSubtract( trace->hit, trace->origin, displacement );
                                gatherDirt += 1.0f - ooDepth * VectorLength( displacement );
@@ -1562,8 +1571,8 @@ void DirtyRawLightmap( int rawLightmapNum )
        trace.recvShadows = lm->recvShadows;
        trace.numSurfaces = lm->numLightSurfaces;
        trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
-       trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
-       trace.testAll = qtrue;
+       trace.inhibitRadius = 0.0f;
+       trace.testAll = qfalse;
        
        /* twosided lighting (may or may not be a good idea for lightmapped stuff) */
        trace.twoSided = qfalse;
@@ -1580,18 +1589,18 @@ void DirtyRawLightmap( int rawLightmapNum )
                }
        }
 
-       noDirty = qfalse;\r
-       for( i = 0; i < trace.numSurfaces; i++ )\r
-       {\r
-               /* get surface */\r
-               info = &surfaceInfos[ trace.surfaces[ i ] ];\r
-\r
-               /* check twosidedness */\r
-               if( info->si->noDirty )\r
-               {\r
-                       noDirty = qtrue;\r
-                       break;\r
-               }\r
+       noDirty = qfalse;
+       for( i = 0; i < trace.numSurfaces; i++ )
+       {
+               /* get surface */
+               info = &surfaceInfos[ trace.surfaces[ i ] ];
+
+               /* check twosidedness */
+               if( info->si->noDirty )
+               {
+                       noDirty = qtrue;
+                       break;
+               }
        }
        
        /* gather dirt */
@@ -1612,11 +1621,11 @@ void DirtyRawLightmap( int rawLightmapNum )
                        if( *cluster < 0 )
                                continue;
 
-                       /* don't apply dirty on this surface */\r
-                       if( noDirty )\r
-                       {\r
-                               *dirt = 1.0f;\r
-                               continue;\r
+                       /* don't apply dirty on this surface */
+                       if( noDirty )
+                       {
+                               *dirt = 1.0f;
+                               continue;
                        }
                        
                        /* copy to trace */
@@ -1714,7 +1723,9 @@ static qboolean SubmapRawLuxel( rawLightmap_t *lm, int x, int y, float bx, float
                //%     normal2 = SUPER_NORMAL( x, y );
        }
        else
-               Sys_Printf( "WARNING: Spurious lightmap S vector\n" );
+       {
+               Error( "Spurious lightmap S vector\n" );
+       }
        
        VectorSubtract( origin2, origin, originVecs[ 0 ] );
        //%     VectorSubtract( normal2, normal, normalVecs[ 0 ] );
@@ -1773,14 +1784,15 @@ SubsampleRawLuxel_r()
 recursively subsamples a luxel until its color gradient is low enough or subsampling limit is reached
 */
 
-static void SubsampleRawLuxel_r( rawLightmap_t *lm, trace_t *trace, vec3_t sampleOrigin, int x, int y, float bias, float *lightLuxel )
+static void SubsampleRawLuxel_r( rawLightmap_t *lm, trace_t *trace, vec3_t sampleOrigin, int x, int y, float bias, float *lightLuxel, float *lightDeluxel )
 {
        int                     b, samples, mapped, lighted;
        int                     cluster[ 4 ];
        vec4_t          luxel[ 4 ];
+       vec3_t          deluxel[ 3 ];
        vec3_t          origin[ 4 ], normal[ 4 ];
        float           biasDirs[ 4 ][ 2 ] = { { -1.0f, -1.0f }, { 1.0f, -1.0f }, { -1.0f, 1.0f }, { 1.0f, 1.0f } };
-       vec3_t          color, total;
+       vec3_t          color, direction = { 0, 0, 0 }, total;
        
        
        /* limit check */
@@ -1817,9 +1829,20 @@ static void SubsampleRawLuxel_r( rawLightmap_t *lm, trace_t *trace, vec3_t sampl
                /* sample light */
 
                LightContributionToSample( trace );
+               if(trace->forceSubsampling > 1.0f)
+               {
+                       /* alphashadow: we subsample as deep as we can */
+                       ++lighted;
+                       ++mapped;
+                       ++mapped;
+               }
                
                /* add to totals (fixme: make contrast function) */
                VectorCopy( trace->color, luxel[ b ] );
+               if(lightDeluxel)
+               {
+                       VectorCopy( trace->directionContribution, deluxel[ b ] );
+               }
                VectorAdd( total, trace->color, total );
                if( (luxel[ b ][ 0 ] + luxel[ b ][ 1 ] + luxel[ b ][ 2 ]) > 0.0f )
                        lighted++;
@@ -1834,7 +1857,7 @@ static void SubsampleRawLuxel_r( rawLightmap_t *lm, trace_t *trace, vec3_t sampl
                {
                        if( cluster[ b ] < 0 )
                                continue;
-                       SubsampleRawLuxel_r( lm, trace, origin[ b ], x, y, (bias * 0.25f), luxel[ b ] );
+                       SubsampleRawLuxel_r( lm, trace, origin[ b ], x, y, (bias * 0.5f), luxel[ b ], lightDeluxel ? deluxel[ b ] : NULL );
                }
        }
        
@@ -1842,12 +1865,20 @@ static void SubsampleRawLuxel_r( rawLightmap_t *lm, trace_t *trace, vec3_t sampl
        //%     VectorClear( color );
        //%     samples = 0;
        VectorCopy( lightLuxel, color );
+       if(lightDeluxel)
+       {
+               VectorCopy( lightDeluxel, direction );
+       }
        samples = 1;
        for( b = 0; b < 4; b++ )
        {
                if( cluster[ b ] < 0 )
                        continue;
                VectorAdd( color, luxel[ b ], color );
+               if(lightDeluxel)
+               {
+                       VectorAdd( direction, deluxel[ b ], direction );
+               }
                samples++;
        }
        
@@ -1858,10 +1889,85 @@ static void SubsampleRawLuxel_r( rawLightmap_t *lm, trace_t *trace, vec3_t sampl
                color[ 0 ] /= samples;
                color[ 1 ] /= samples;
                color[ 2 ] /= samples;
-               
+
                /* add to color */
                VectorCopy( color, lightLuxel );
                lightLuxel[ 3 ] += 1.0f;
+
+               if(lightDeluxel)
+               {
+                       direction[ 0 ] /= samples;
+                       direction[ 1 ] /= samples;
+                       direction[ 2 ] /= samples;
+                       VectorCopy( direction, lightDeluxel );
+               }
+       }
+}
+
+/* A mostly Gaussian-like bounded random distribution (sigma is expected standard deviation) */
+static void GaussLikeRandom(float sigma, float *x, float *y)
+{
+       float r;
+       r = Random() * 2 * Q_PI;
+       *x = sigma * 2.73861278752581783822 * cos(r);
+       *y = sigma * 2.73861278752581783822 * sin(r);
+       r = Random();
+       r = 1 - sqrt(r);
+       r = 1 - sqrt(r);
+       *x *= r;
+       *y *= r;
+}
+static void RandomSubsampleRawLuxel( rawLightmap_t *lm, trace_t *trace, vec3_t sampleOrigin, int x, int y, float bias, float *lightLuxel, float *lightDeluxel )
+{
+       int                     b, mapped;
+       int                     cluster;
+       vec3_t          origin, normal;
+       vec3_t          total, totaldirection;
+       float           dx, dy;
+       
+       VectorClear( total );
+       VectorClear( totaldirection );
+       mapped = 0;
+       for(b = 0; b < lightSamples; ++b)
+       {
+               /* set origin */
+               VectorCopy( sampleOrigin, origin );
+               GaussLikeRandom(bias, &dx, &dy);
+
+               /* calculate position */
+               if( !SubmapRawLuxel( lm, x, y, dx, dy, &cluster, origin, normal ) )
+               {
+                       cluster = -1;
+                       continue;
+               }
+               mapped++;
+
+               trace->cluster = cluster;
+               VectorCopy( origin, trace->origin );
+               VectorCopy( normal, trace->normal );
+
+               LightContributionToSample( trace );
+               VectorAdd( total, trace->color, total );
+               if(lightDeluxel)
+               {
+                       VectorAdd( totaldirection, trace->directionContribution, totaldirection );
+               }
+       }
+
+       /* add to luxel */
+       if( mapped > 0 )
+       {
+               /* average */
+               lightLuxel[ 0 ] = total[ 0 ] / mapped;
+               lightLuxel[ 1 ] = total[ 1 ] / mapped;
+               lightLuxel[ 2 ] = total[ 2 ] / mapped;
+
+               if(lightDeluxel)
+               {
+                       lightDeluxel[ 0 ] = totaldirection[ 0 ] / mapped;
+                       lightDeluxel[ 1 ] = totaldirection[ 1 ] / mapped;
+                       lightDeluxel[ 2 ] = totaldirection[ 2 ] / mapped;
+               }
        }
 }
 
@@ -1874,18 +1980,21 @@ illuminates the luxels
 
 #define STACK_LL_SIZE                  (SUPER_LUXEL_SIZE * 64 * 64)
 #define LIGHT_LUXEL( x, y )            (lightLuxels + ((((y) * lm->sw) + (x)) * SUPER_LUXEL_SIZE))
+#define LIGHT_DELUXEL( x, y )          (lightDeluxels + ((((y) * lm->sw) + (x)) * SUPER_DELUXEL_SIZE))
 
 void IlluminateRawLightmap( int rawLightmapNum )
 {
-       int                                     i, t, x, y, sx, sy, size, llSize, luxelFilterRadius, lightmapNum;
+       int                                     i, t, x, y, sx, sy, size, luxelFilterRadius, lightmapNum;
        int                                     *cluster, *cluster2, mapped, lighted, totalLighted;
+       size_t                                  llSize, ldSize;
        rawLightmap_t           *lm;
        surfaceInfo_t           *info;
        qboolean                        filterColor, filterDir;
        float                           brightness;
        float                           *origin, *normal, *dirt, *luxel, *luxel2, *deluxel, *deluxel2;
-       float                           *lightLuxels, *lightLuxel, samples, filterRadius, weight;
-       vec3_t                          color, averageColor, averageDir, total, temp, temp2;
+       unsigned char                   *flag;
+       float                           *lightLuxels, *lightDeluxels, *lightLuxel, *lightDeluxel, samples, filterRadius, weight;
+       vec3_t                          color, direction, averageColor, averageDir, total, temp, temp2;
        float                           tests[ 4 ][ 2 ] = { { 0.0f, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
        trace_t                         trace;
        float                           stackLightLuxels[ STACK_LL_SIZE ];
@@ -1999,10 +2108,15 @@ void IlluminateRawLightmap( int rawLightmapNum )
        {
                /* allocate temporary per-light luxel storage */
                llSize = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( float );
+               ldSize = lm->sw * lm->sh * SUPER_DELUXEL_SIZE * sizeof( float );
                if( llSize <= (STACK_LL_SIZE * sizeof( float )) )
                        lightLuxels = stackLightLuxels;
                else
                        lightLuxels = safe_malloc( llSize );
+               if(deluxemap)
+                       lightDeluxels = safe_malloc( ldSize );
+               else
+                       lightDeluxels = NULL;
                
                /* clear luxels */
                //%     memset( lm->superLuxels[ 0 ], 0, llSize );
@@ -2076,8 +2190,31 @@ void IlluminateRawLightmap( int rawLightmapNum )
                        
                        /* setup */
                        memset( lightLuxels, 0, llSize );
+                       if(deluxemap)
+                               memset( lightDeluxels, 0, ldSize );
                        totalLighted = 0;
                        
+                       /* determine filter radius */
+                       filterRadius = lm->filterRadius > trace.light->filterRadius
+                               ? lm->filterRadius
+                               : trace.light->filterRadius;
+                       if( filterRadius < 0.0f )
+                               filterRadius = 0.0f;
+                       
+                       /* set luxel filter radius */
+                       luxelFilterRadius = superSample * filterRadius / lm->sampleSize;
+                       if( luxelFilterRadius == 0 && (filterRadius > 0.0f || filter) )
+                               luxelFilterRadius = 1;
+
+                       /* allocate sampling flags storage */
+                       if((lightSamples > 1 || lightRandomSamples) && luxelFilterRadius == 0)
+                       {
+                               size = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( unsigned char );
+                               if(lm->superFlags == NULL)
+                                       lm->superFlags = safe_malloc( size );
+                               memset( (void *) lm->superFlags, 0, size );
+                       }
+
                        /* initial pass, one sample per luxel */
                        for( y = 0; y < lm->sh; y++ )
                        {
@@ -2090,9 +2227,10 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                        
                                        /* get particulars */
                                        lightLuxel = LIGHT_LUXEL( x, y );
-                                       deluxel = SUPER_DELUXEL( x, y );
+                                       lightDeluxel = LIGHT_DELUXEL( x, y );
                                        origin = SUPER_ORIGIN( x, y );
                                        normal = SUPER_NORMAL( x, y );
+                                       flag = SUPER_FLAG( x, y );
 
 #if 0
                                        ////////// 27's temp hack for testing edge clipping ////
@@ -2117,12 +2255,20 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                                LightContributionToSample( &trace );
                                                VectorCopy( trace.color, lightLuxel );
 
-                                               /* add the contribution to the deluxemap */\r
-                                               if( deluxemap )\r
-                                                       VectorAdd( deluxel, trace.directionContribution, deluxel );
+                                               /* add the contribution to the deluxemap */
+                                               if( deluxemap )
+                                               {
+                                                       VectorCopy( trace.directionContribution, lightDeluxel );
+                                               }
 
+                                               /* check for evilness */
+                                               if(trace.forceSubsampling > 1.0f && (lightSamples > 1 || lightRandomSamples) && luxelFilterRadius == 0)
+                                               {
+                                                       totalLighted++;
+                                                       *flag |= FLAG_FORCE_SUBSAMPLING; /* force */
+                                               }
                                                /* add to count */
-                                               if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
+                                               else if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
                                                        totalLighted++;
                                        }
                                }
@@ -2132,21 +2278,9 @@ void IlluminateRawLightmap( int rawLightmapNum )
                        if( totalLighted == 0 )
                                continue;
                        
-                       /* determine filter radius */
-                       filterRadius = lm->filterRadius > trace.light->filterRadius
-                               ? lm->filterRadius
-                               : trace.light->filterRadius;
-                       if( filterRadius < 0.0f )
-                               filterRadius = 0.0f;
-                       
-                       /* set luxel filter radius */
-                       luxelFilterRadius = superSample * filterRadius / lm->sampleSize;
-                       if( luxelFilterRadius == 0 && (filterRadius > 0.0f || filter) )
-                               luxelFilterRadius = 1;
-                       
                        /* secondary pass, adaptive supersampling (fixme: use a contrast function to determine if subsampling is necessary) */
                        /* 2003-09-27: changed it so filtering disamples supersampling, as it would waste time */
-                       if( lightSamples > 1 && luxelFilterRadius == 0 )
+                       if( (lightSamples > 1 || lightRandomSamples) && luxelFilterRadius == 0 )
                        {
                                /* walk luxels */
                                for( y = 0; y < (lm->sh - 1); y++ )
@@ -2172,6 +2306,14 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                                        mapped++;
                                                        
                                                        /* get luxel */
+                                                       flag = SUPER_FLAG( sx, sy );
+                                                       if(*flag & FLAG_FORCE_SUBSAMPLING)
+                                                       {
+                                                               /* force a lighted/mapped discrepancy so we subsample */
+                                                               ++lighted;
+                                                               ++mapped;
+                                                               ++mapped;
+                                                       }
                                                        lightLuxel = LIGHT_LUXEL( sx, sy );
                                                        VectorAdd( total, lightLuxel, total );
                                                        if( (lightLuxel[ 0 ] + lightLuxel[ 1 ] + lightLuxel[ 2 ]) > 0.0f )
@@ -2195,7 +2337,11 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                                                cluster = SUPER_CLUSTER( sx, sy );
                                                                if( *cluster < 0 )
                                                                        continue;
+                                                               flag = SUPER_FLAG( sx, sy );
+                                                               if(*flag & FLAG_ALREADY_SUBSAMPLED) // already subsampled
+                                                                       continue;
                                                                lightLuxel = LIGHT_LUXEL( sx, sy );
+                                                               lightDeluxel = LIGHT_DELUXEL( sx, sy );
                                                                origin = SUPER_ORIGIN( sx, sy );
                                                                
                                                                /* only subsample shadowed luxels */
@@ -2203,7 +2349,12 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                                                //%             continue;
                                                                
                                                                /* subsample it */
-                                                               SubsampleRawLuxel_r( lm, &trace, origin, sx, sy, 0.25f, lightLuxel );
+                                                               if(lightRandomSamples)
+                                                                       RandomSubsampleRawLuxel( lm, &trace, origin, sx, sy, 0.5f * lightSamplesSearchBoxSize, lightLuxel, deluxemap ? lightDeluxel : NULL );
+                                                               else
+                                                                       SubsampleRawLuxel_r( lm, &trace, origin, sx, sy, 0.25f * lightSamplesSearchBoxSize, lightLuxel, deluxemap ? lightDeluxel : NULL );
+
+                                                               *flag |= FLAG_ALREADY_SUBSAMPLED;
                                                                
                                                                /* debug code to colorize subsampled areas to yellow */
                                                                //%     luxel = SUPER_LUXEL( lightmapNum, sx, sy );
@@ -2245,7 +2396,7 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                lm->superLuxels[ lightmapNum ] = safe_malloc( size );
                                memset( lm->superLuxels[ lightmapNum ], 0, size );
                        }
-                       
+
                        /* set style */
                        if( lightmapNum > 0 )
                        {
@@ -2269,6 +2420,7 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                        {
                                                /* setup */
                                                VectorClear( averageColor );
+                                               VectorClear( averageDir );
                                                samples = 0.0f;
                                                
                                                /* cheaper distance-based filtering */
@@ -2287,6 +2439,7 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                                                if( *cluster < 0 )
                                                                        continue;
                                                                lightLuxel = LIGHT_LUXEL( sx, sy );
+                                                               lightDeluxel = LIGHT_DELUXEL( sx, sy );
                                                                
                                                                /* create weight */
                                                                weight = (abs( sx - x ) == luxelFilterRadius ? 0.5f : 1.0f);
@@ -2295,6 +2448,11 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                                                /* scale luxel by filter weight */
                                                                VectorScale( lightLuxel, weight, color );
                                                                VectorAdd( averageColor, color, averageColor );
+                                                               if(deluxemap)
+                                                               {
+                                                                       VectorScale( lightDeluxel, weight, direction );
+                                                                       VectorAdd( averageDir, direction, averageDir );
+                                                               }
                                                                samples += weight;
                                                        }
                                                }
@@ -2322,6 +2480,15 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                                        luxel[ 1 ] += averageColor[ 1 ] / samples;
                                                        luxel[ 2 ] += averageColor[ 2 ] / samples;
                                                }
+                                               
+                                               if(deluxemap)
+                                               {
+                                                       /* scale into luxel */
+                                                       deluxel = SUPER_DELUXEL( x, y );
+                                                       deluxel[ 0 ] += averageDir[ 0 ] / samples;
+                                                       deluxel[ 1 ] += averageDir[ 1 ] / samples;
+                                                       deluxel[ 2 ] += averageDir[ 2 ] / samples;
+                                               }
                                        }
                                        
                                        /* single sample */
@@ -2329,7 +2496,9 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                        {
                                                /* get particulars */
                                                lightLuxel = LIGHT_LUXEL( x, y );
+                                               lightDeluxel = LIGHT_DELUXEL( x, y );
                                                luxel = SUPER_LUXEL( lightmapNum, x, y );
+                                               deluxel = SUPER_DELUXEL( x, y );
                                                
                                                /* handle negative light */
                                                if( trace.light->flags & LIGHT_NEGATIVE )
@@ -2345,6 +2514,11 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                                /* handle normal light */
                                                else
                                                        VectorAdd( luxel, lightLuxel, luxel );
+
+                                               if(deluxemap)
+                                               {
+                                                       VectorAdd( deluxel, lightDeluxel, deluxel );
+                                               }
                                        }
                                }
                        }
@@ -2353,6 +2527,9 @@ void IlluminateRawLightmap( int rawLightmapNum )
                /* free temporary luxels */
                if( lightLuxels != stackLightLuxels )
                        free( lightLuxels );
+               
+               if(deluxemap)
+                       free( lightDeluxels );
        }
        
        /* free light list */
@@ -2585,7 +2762,7 @@ void IlluminateVertexes( int num )
        rawLightmap_t           *lm;
        bspDrawVert_t           *verts;
        trace_t                         trace;
-       float                           floodLightAmount;\r
+       float                           floodLightAmount;
        vec3_t                          floodColor;
        
        
@@ -2670,12 +2847,12 @@ void IlluminateVertexes( int num )
                                                dirt = 1.0f;
 
                                        /* jal: floodlight */
-                                       floodLightAmount = 0.0f;\r
-                                       VectorClear( floodColor );\r
-                                       if( floodlighty && !bouncing )\r
-                                       {\r
-                                               floodLightAmount = floodlightIntensity * FloodLightForSample( &trace, floodlightDistance, floodlight_lowquality );\r
-                                               VectorScale( floodlightRGB, floodLightAmount, floodColor );\r
+                                       floodLightAmount = 0.0f;
+                                       VectorClear( floodColor );
+                                       if( floodlighty && !bouncing )
+                                       {
+                                               floodLightAmount = floodlightIntensity * FloodLightForSample( &trace, floodlightDistance, floodlight_lowquality );
+                                               VectorScale( floodlightRGB, floodLightAmount, floodColor );
                                        }
 
                                        /* trace */
@@ -2704,16 +2881,16 @@ void IlluminateVertexes( int num )
                                        radVertLuxel[ 2 ] <= ambientColor[ 2 ] )
                                {
                                        /* nudge the sample point around a bit */
-                                       for( x = 0; x < 4; x++ )
+                                       for( x = 0; x < 5; x++ )
                                        {
                                                /* two's complement 0, 1, -1, 2, -2, etc */
                                                x1 = ((x >> 1) ^ (x & 1 ? -1 : 0)) + (x & 1);
                                                
-                                               for( y = 0; y < 4; y++ )
+                                               for( y = 0; y < 5; y++ )
                                                {
                                                        y1 = ((y >> 1) ^ (y & 1 ? -1 : 0)) + (y & 1);
                                                        
-                                                       for( z = 0; z < 4; z++ )
+                                                       for( z = 0; z < 5; z++ )
                                                        {
                                                                z1 = ((z >> 1) ^ (z & 1 ? -1 : 0)) + (z & 1);
                                                                
@@ -2726,6 +2903,21 @@ void IlluminateVertexes( int num )
                                                                trace.cluster = ClusterForPointExtFilter( origin, VERTEX_EPSILON, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ] );
                                                                if( trace.cluster < 0 )
                                                                        continue;
+
+                                                               /* r7 dirt */
+                                                               if( dirty && !bouncing )
+                                                                       dirt = DirtForSample( &trace );
+                                                               else
+                                                                       dirt = 1.0f;
+
+                                                               /* jal: floodlight */
+                                                               floodLightAmount = 0.0f;
+                                                               VectorClear( floodColor );
+                                                               if( floodlighty && !bouncing )
+                                                               {
+                                                                       floodLightAmount = floodlightIntensity * FloodLightForSample( &trace, floodlightDistance, floodlight_lowquality );
+                                                                       VectorScale( floodlightRGB, floodLightAmount, floodColor );
+                                                               }
                                                                                                                        
                                                                /* trace */
                                                                LightingAtSample( &trace, ds->vertexStyles, colors );
@@ -2948,9 +3140,10 @@ SetupBrushes()
 determines opaque brushes in the world and find sky shaders for sunlight calculations
 */
 
-void SetupBrushes( void )
+void SetupBrushesFlags( int mask_any, int test_any, int mask_all, int test_all )
 {
-       int                             i, j, b, compileFlags;
+       int                             i, j, b;
+       unsigned int                    compileFlags, allCompileFlags;
        qboolean                inside;
        bspBrush_t              *brush;
        bspBrushSide_t  *side;
@@ -2979,23 +3172,25 @@ void SetupBrushes( void )
                /* check all sides */
                inside = qtrue;
                compileFlags = 0;
+               allCompileFlags = ~(0u);
                for( j = 0; j < brush->numSides && inside; j++ )
                {
                        /* do bsp shader calculations */
                        side = &bspBrushSides[ brush->firstSide + j ];
                        shader = &bspShaders[ side->shaderNum ];
-                       
+
                        /* get shader info */
-                       si = ShaderInfoForShader( shader->shader );
+                       si = ShaderInfoForShaderNull( shader->shader );
                        if( si == NULL )
                                continue;
                        
                        /* or together compile flags */
                        compileFlags |= si->compileFlags;
+                       allCompileFlags &= si->compileFlags;
                }
-               
+
                /* determine if this brush is opaque to light */
-               if( !(compileFlags & C_TRANSLUCENT) )
+               if( (compileFlags & mask_any) == test_any && (allCompileFlags & mask_all) == test_all )
                {
                        opaqueBrushes[ b >> 3 ] |= (1 << (b & 7));
                        numOpaqueBrushes++;
@@ -3006,6 +3201,10 @@ void SetupBrushes( void )
        /* emit some statistics */
        Sys_FPrintf( SYS_VRB, "%9d opaque brushes\n", numOpaqueBrushes );
 }
+void SetupBrushes( void )
+{
+       SetupBrushesFlags(C_TRANSLUCENT, 0, 0, 0);
+}
 
 
 
@@ -3016,7 +3215,7 @@ determines if two clusters are visible to each other using the PVS
 
 qboolean ClusterVisible( int a, int b )
 {
-       int                     portalClusters, leafBytes;
+       int                     leafBytes;
        byte            *pvs;
        
        
@@ -3033,7 +3232,7 @@ qboolean ClusterVisible( int a, int b )
                return qtrue;
        
        /* get pvs data */
-       portalClusters = ((int *) bspVisBytes)[ 0 ];
+       /* portalClusters = ((int *) bspVisBytes)[ 0 ]; */
        leafBytes = ((int*) bspVisBytes)[ 1 ];
        pvs = bspVisBytes + VIS_HEADER_SIZE + (a * leafBytes);
        
@@ -3337,7 +3536,7 @@ void SetupEnvelopes( qboolean forGrid, qboolean fastFlag )
        int                     i, x, y, z, x1, y1, z1;
        light_t         *light, *light2, **owner;
        bspLeaf_t       *leaf;
-       vec3_t          origin, dir, mins, maxs, nullVector = { 0, 0, 0 };
+       vec3_t          origin, dir, mins, maxs;
        float           radius, intensity;
        light_t         *buckets[ 256 ];
        
@@ -3433,23 +3632,30 @@ void SetupEnvelopes( qboolean forGrid, qboolean fastFlag )
                                /* handle area lights */
                                if( exactPointToPolygon && light->type == EMIT_AREA && light->w != NULL )
                                {
-                                       /* ugly hack to calculate extent for area lights, but only done once */
-                                       VectorScale( light->normal, -1.0f, dir );
-                                       for( radius = 100.0f; radius < 130000.0f && light->envelope == 0; radius += 10.0f )
+                                       light->envelope = MAX_WORLD_COORD * 8.0f;
+
+                                       /* check for fast mode */
+                                       if( (light->flags & LIGHT_FAST) || (light->flags & LIGHT_FAST_TEMP) )
                                        {
-                                               float   factor;
-                                               
-                                               VectorMA( light->origin, radius, light->normal, origin );
-                                               factor = PointToPolygonFormFactor( origin, dir, light->w );
-                                               if( factor < 0.0f )
-                                                       factor *= -1.0f;
-                                               if( (factor * light->add) <= light->falloffTolerance )
-                                                       light->envelope = radius;
+                                               /* ugly hack to calculate extent for area lights, but only done once */
+                                               VectorScale( light->normal, -1.0f, dir );
+                                               for( radius = 100.0f; radius < MAX_WORLD_COORD * 8.0f; radius += 10.0f )
+                                               {
+                                                       float   factor;
+                                                       
+                                                       VectorMA( light->origin, radius, light->normal, origin );
+                                                       factor = PointToPolygonFormFactor( origin, dir, light->w );
+                                                       if( factor < 0.0f )
+                                                               factor *= -1.0f;
+                                                       if( (factor * light->add) <= light->falloffTolerance )
+                                                       {
+                                                               light->envelope = radius;
+                                                               break;
+                                                       }
+                                               }
                                        }
                                        
-                                       /* check for fast mode */
-                                       if( !(light->flags & LIGHT_FAST) && !(light->flags & LIGHT_FAST_TEMP) )
-                                               light->envelope = MAX_WORLD_COORD * 8.0f;
+                                       intensity = light->photons; /* hopefully not used */
                                }
                                else
                                {
@@ -3463,30 +3669,42 @@ void SetupEnvelopes( qboolean forGrid, qboolean fastFlag )
                                        /* solve distance for non-distance lights */
                                        if( !(light->flags & LIGHT_ATTEN_DISTANCE) )
                                                light->envelope = MAX_WORLD_COORD * 8.0f;
-                                       
-                                       /* solve distance for linear lights */
-                                       else if( (light->flags & LIGHT_ATTEN_LINEAR ) )
-                                               //% light->envelope = ((intensity / light->falloffTolerance) * linearScale - 1 + radius) / light->fade;
-                                               light->envelope = ((intensity * linearScale) - light->falloffTolerance) / light->fade;
-
-                                               /*
-                                               add = angle * light->photons * linearScale - (dist * light->fade);
-                                               T = (light->photons * linearScale) - (dist * light->fade);
-                                               T + (dist * light->fade) = (light->photons * linearScale);
-                                               dist * light->fade = (light->photons * linearScale) - T;
-                                               dist = ((light->photons * linearScale) - T) / light->fade;
-                                               */
-                                       
-                                       /* solve for inverse square falloff */
+                                               
+                                       else if( (light->flags & LIGHT_FAST) || (light->flags & LIGHT_FAST_TEMP) )
+                                       {
+                                               /* solve distance for linear lights */
+                                               if( (light->flags & LIGHT_ATTEN_LINEAR ) )
+                                                       light->envelope = ((intensity * linearScale) - light->falloffTolerance) / light->fade;
+
+                                                       /*
+                                                       add = angle * light->photons * linearScale - (dist * light->fade);
+                                                       T = (light->photons * linearScale) - (dist * light->fade);
+                                                       T + (dist * light->fade) = (light->photons * linearScale);
+                                                       dist * light->fade = (light->photons * linearScale) - T;
+                                                       dist = ((light->photons * linearScale) - T) / light->fade;
+                                                       */
+                                               
+                                               /* solve for inverse square falloff */
+                                               else
+                                                       light->envelope = sqrt( intensity / light->falloffTolerance ) + radius;
+                                                       
+                                                       /*
+                                                       add = light->photons / (dist * dist);
+                                                       T = light->photons / (dist * dist);
+                                                       T * (dist * dist) = light->photons;
+                                                       dist = sqrt( light->photons / T );
+                                                       */
+                                       }
                                        else
-                                               light->envelope = sqrt( intensity / light->falloffTolerance ) + radius;
+                                       {
+                                               /* solve distance for linear lights */
+                                               if( (light->flags & LIGHT_ATTEN_LINEAR ) )
+                                                       light->envelope = (intensity * linearScale) / light->fade;
                                                
-                                               /*
-                                               add = light->photons / (dist * dist);
-                                               T = light->photons / (dist * dist);
-                                               T * (dist * dist) = light->photons;
-                                               dist = sqrt( light->photons / T );
-                                               */
+                                               /* can't cull these */
+                                               else
+                                                       light->envelope = MAX_WORLD_COORD * 8.0f;
+                                       }
                                }
                                
                                /* chop radius against pvs */
@@ -3827,7 +4045,7 @@ void SetupFloodLight( void )
        int             i, j;
        float   angle, elevation, angleStep, elevationStep;
        const char      *value;
-       double v1,v2,v3,v4,v5;
+       double v1,v2,v3,v4,v5,v6;
 
        /* note it */
        Sys_FPrintf( SYS_VRB, "--- SetupFloodLight ---\n" );
@@ -3861,8 +4079,9 @@ void SetupFloodLight( void )
                v1=v2=v3=0;
                v4=floodlightDistance;
                v5=floodlightIntensity;
+               v6=floodlightDirectionScale;
 
-               sscanf( value, "%lf %lf %lf %lf %lf", &v1, &v2, &v3, &v4, &v5);
+               sscanf( value, "%lf %lf %lf %lf %lf %lf", &v1, &v2, &v3, &v4, &v5, &v6);
 
                floodlightRGB[0]=v1;
                floodlightRGB[1]=v2;
@@ -3870,25 +4089,31 @@ void SetupFloodLight( void )
 
                if (VectorLength(floodlightRGB)==0)
                {
-                       VectorSet(floodlightRGB,240,240,255);
+                       VectorSet(floodlightRGB,0.94,0.94,1.0);
                }
 
                if (v4<1) v4=1024;
                if (v5<1) v5=128;
+               if (v6<0) v6=1;
 
                floodlightDistance=v4;
                floodlightIntensity=v5;
+               floodlightDirectionScale=v6;
 
                floodlighty = qtrue;
                Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
        }
        else
        {
-               VectorSet(floodlightRGB,240,240,255);
-               //floodlighty = qtrue;
-               //Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
+               VectorSet(floodlightRGB,0.94,0.94,1.0);
        }
-       VectorNormalize(floodlightRGB,floodlightRGB);
+       if(colorsRGB)
+       {
+               floodlightRGB[0] = Image_LinearFloatFromsRGBFloat(floodlightRGB[0]);
+               floodlightRGB[1] = Image_LinearFloatFromsRGBFloat(floodlightRGB[1]);
+               floodlightRGB[2] = Image_LinearFloatFromsRGBFloat(floodlightRGB[2]);
+       }
+       ColorNormalize(floodlightRGB,floodlightRGB);
 }
 
 /*
@@ -3972,7 +4197,7 @@ float FloodLightForSample( trace_t *trace , float floodLightDistance, qboolean f
                        TraceLine( trace );
                        contribution=1;
 
-                       if (trace->compileFlags & C_SKY )
+                       if ( trace->compileFlags & C_SKY || trace->compileFlags & C_TRANSLUCENT )
                        {
                                contribution=1.0f;
                        }
@@ -4156,7 +4381,7 @@ void FloodLightRawLightmap( int rawLightmapNum )
 
        /* global pass */
        if (floodlighty && floodlightIntensity)
-               FloodLightRawLightmapPass(lm, floodlightRGB, floodlightIntensity, floodlightDistance, floodlight_lowquality, 1.0f);
+               FloodLightRawLightmapPass(lm, floodlightRGB, floodlightIntensity, floodlightDistance, floodlight_lowquality, floodlightDirectionScale);
 
        /* custom pass */
        if (lm->floodlightIntensity)
@@ -4222,17 +4447,17 @@ void FloodlightIlluminateLightmap( rawLightmap_t *lm )
                                if (luxel[3]==0) luxel[3]=1;
 
                                /* add to deluxemap */
-                               if (deluxemap && floodlight[3] > 0)\r
+                               if (deluxemap && floodlight[3] > 0)
                                {
-                                       vec3_t                          lightvector;\r
-\r
+                                       vec3_t                          lightvector;
+
                                        normal = SUPER_NORMAL( x, y );
-                                       brightness = RGBTOGRAY( floodlight ) * ( 1.0f/255.0f ) * floodlight[3];\r
-\r
-                                       // use AT LEAST this amount of contribution from ambient for the deluxemap, fixes points that receive ZERO light\r
-                                       if(brightness < 0.00390625f)\r
-                                               brightness = 0.00390625f;\r
-\r
+                                       brightness = RGBTOGRAY( floodlight ) * ( 1.0f/255.0f ) * floodlight[3];
+
+                                       // use AT LEAST this amount of contribution from ambient for the deluxemap, fixes points that receive ZERO light
+                                       if(brightness < 0.00390625f)
+                                               brightness = 0.00390625f;
+
                                        VectorScale( normal, brightness, lightvector );
                                        VectorAdd( deluxel, lightvector, deluxel );
                                }