]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/light_ydnar.c
no, we do NOT want to ignore caulk
[xonotic/netradiant.git] / tools / quake3 / q3map2 / light_ydnar.c
index 69f707412c847bd06096f4a30bc4133aa805d394..bf5bc36c34b90a72d785696daa837368e45f7918 100644 (file)
@@ -120,6 +120,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 +1162,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 );
+                                               }
                                        }
                                }
                                
@@ -1425,7 +1438,7 @@ float DirtForSample( trace_t *trace )
        VectorCopy( trace->normal, normal );
        
        /* check if the normal is aligned to the world-up */
-       if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f )
+       if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f && ( normal[ 2 ] == 1.0f || normal[ 2 ] == -1.0f ) )
        {
                if( normal[ 2 ] == 1.0f )               
                {
@@ -1471,7 +1484,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 );
@@ -1546,7 +1559,8 @@ void DirtyRawLightmap( int rawLightmapNum )
        rawLightmap_t           *lm;
        surfaceInfo_t           *info;
        trace_t                         trace;
-       
+       qboolean                        noDirty;
+
        
        /* bail if this number exceeds the number of raw lightmaps */
        if( rawLightmapNum >= numRawLightmaps )
@@ -1561,7 +1575,7 @@ void DirtyRawLightmap( int rawLightmapNum )
        trace.recvShadows = lm->recvShadows;
        trace.numSurfaces = lm->numLightSurfaces;
        trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
-       trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
+       trace.inhibitRadius = 0.0f;
        trace.testAll = qfalse;
        
        /* twosided lighting (may or may not be a good idea for lightmapped stuff) */
@@ -1578,6 +1592,20 @@ void DirtyRawLightmap( int rawLightmapNum )
                        break;
                }
        }
+
+       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 */
        for( y = 0; y < lm->sh; y++ )
@@ -1596,6 +1624,13 @@ void DirtyRawLightmap( int rawLightmapNum )
                        /* only look at mapped luxels */
                        if( *cluster < 0 )
                                continue;
+
+                       /* don't apply dirty on this surface */
+                       if( noDirty )
+                       {
+                               *dirt = 1.0f;
+                               continue;
+                       }
                        
                        /* copy to trace */
                        trace.cluster = *cluster;
@@ -1692,7 +1727,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 ] );
@@ -1751,14 +1788,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 */
@@ -1795,9 +1833,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++;
@@ -1812,7 +1861,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 );
                }
        }
        
@@ -1820,12 +1869,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++;
        }
        
@@ -1836,10 +1893,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;
+               }
        }
 }
 
@@ -1852,23 +1984,24 @@ 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 ];
-       vec3_t                          flood;
-       float                           *floodlight;
        
        
        /* bail if this number exceeds the number of raw lightmaps */
@@ -1979,10 +2112,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 );
@@ -2008,11 +2146,12 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                        VectorCopy( ambientColor, luxel );
                                        if( deluxemap )
                                        {
-                                               brightness = ambientColor[ 0 ] * 0.3f + ambientColor[ 1 ] * 0.59f + ambientColor[ 2 ] * 0.11f;
-                                               brightness *= (1.0 / 255.0);
+                                               brightness = RGBTOGRAY( ambientColor ) * ( 1.0f/255.0f );
+
                                                // 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, deluxel );
                                        }
                                        luxel[ 3 ] = 1.0f;
@@ -2055,8 +2194,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++ )
                        {
@@ -2069,9 +2231,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 ////
@@ -2096,22 +2259,21 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                                LightContributionToSample( &trace );
                                                VectorCopy( trace.color, lightLuxel );
 
-                                               /* add to count */
-                                               if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
-                                                       totalLighted++;
-                                       }
-                                       
-                                       /* add to light direction map (fixme: use luxel normal as starting point for deluxel?) */
-                                       if( deluxemap )
-                                       {
-                                               if(DotProduct(normal, trace.direction) > 0) // do not take light from the back side
+                                               /* 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)
                                                {
-                                                       /* color to grayscale (photoshop rgb weighting) */
-                                                       brightness = trace.color[ 0 ] * 0.3f + trace.color[ 1 ] * 0.59f + trace.color[ 2 ] * 0.11f;
-                                                       brightness *= (1.0 / 255.0);
-                                                       VectorScale( trace.direction, brightness, trace.direction );
-                                                       VectorAdd( deluxel, trace.direction, deluxel );
+                                                       totalLighted++;
+                                                       *flag |= FLAG_FORCE_SUBSAMPLING; /* force */
                                                }
+                                               /* add to count */
+                                               else if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
+                                                       totalLighted++;
                                        }
                                }
                        }
@@ -2120,21 +2282,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++ )
@@ -2160,6 +2310,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 )
@@ -2183,7 +2341,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 */
@@ -2191,7 +2353,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 );
@@ -2233,7 +2400,7 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                lm->superLuxels[ lightmapNum ] = safe_malloc( size );
                                memset( lm->superLuxels[ lightmapNum ], 0, size );
                        }
-                       
+
                        /* set style */
                        if( lightmapNum > 0 )
                        {
@@ -2257,6 +2424,7 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                        {
                                                /* setup */
                                                VectorClear( averageColor );
+                                               VectorClear( averageDir );
                                                samples = 0.0f;
                                                
                                                /* cheaper distance-based filtering */
@@ -2275,6 +2443,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);
@@ -2283,6 +2452,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;
                                                        }
                                                }
@@ -2310,6 +2484,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 */
@@ -2317,7 +2500,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 )
@@ -2333,6 +2518,11 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                                /* handle normal light */
                                                else
                                                        VectorAdd( luxel, lightLuxel, luxel );
+
+                                               if(deluxemap)
+                                               {
+                                                       VectorAdd( deluxel, lightDeluxel, deluxel );
+                                               }
                                        }
                                }
                        }
@@ -2341,61 +2531,17 @@ void IlluminateRawLightmap( int rawLightmapNum )
                /* free temporary luxels */
                if( lightLuxels != stackLightLuxels )
                        free( lightLuxels );
+               
+               if(deluxemap)
+                       free( lightDeluxels );
        }
        
        /* free light list */
        FreeTraceLights( &trace );
        
-       /*      -----------------------------------------------------------------
-               floodlight pass
-               ----------------------------------------------------------------- */
-
+       /* floodlight pass */
        if( floodlighty )
-       {
-               /* walk lightmaps */
-               for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-               {
-                       /* early out */
-                       if( lm->superLuxels[ lightmapNum ] == NULL )
-                               continue;
-
-                       /* apply floodlight to each luxel */
-                       for( y = 0; y < lm->sh; y++ )
-                       {
-                               for( x = 0; x < lm->sw; x++ )
-                               {
-                                       /* get cluster */
-                                       cluster = SUPER_CLUSTER( x, y );
-                                       if( *cluster < 0 )
-                                               continue;
-
-                                       /* get particulars */
-                                       luxel = SUPER_LUXEL( lightmapNum, x, y );
-                                       floodlight = SUPER_FLOODLIGHT( x, y );
-
-                                       flood[0]=floodlightRGB[0]*floodlightIntensity;
-                                       flood[1]=floodlightRGB[1]*floodlightIntensity;
-                                       flood[2]=floodlightRGB[2]*floodlightIntensity;
-
-                                       /* scale light value */
-                                       VectorScale( flood, *floodlight, flood );
-                                       luxel[0]+=flood[0];
-                                       luxel[1]+=flood[1];
-                                       luxel[2]+=flood[2];
-
-                                       if (luxel[3]==0) luxel[3]=1;
-
-                                       if(deluxemap)
-                                       {
-                                               brightness = flood[ 0 ] * 0.3f + flood[ 1 ] * 0.59f + flood[ 2 ] * 0.11f;
-                                               brightness *= (1.0 / 255.0);
-                                               VectorScale( normal, brightness, temp );
-                                               VectorAdd( deluxel, temp, deluxel );
-                                       }
-                               }
-                       }
-               }
-       }
+               FloodlightIlluminateLightmap(lm);
 
        if (debugnormals)
        {
@@ -2404,7 +2550,7 @@ void IlluminateRawLightmap( int rawLightmapNum )
                        /* early out */
                        if( lm->superLuxels[ lightmapNum ] == NULL )
                                continue;
-
+                       
                        for( y = 0; y < lm->sh; y++ )
                        {
                                for( x = 0; x < lm->sw; x++ )
@@ -2413,11 +2559,11 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                        cluster = SUPER_CLUSTER( x, y );
                                        //%     if( *cluster < 0 )
                                        //%             continue;
-
+                                       
                                        /* get particulars */
                                        luxel = SUPER_LUXEL( lightmapNum, x, y );
                                        normal = SUPER_NORMAL (  x, y );
-
+               
                                        luxel[0]=(normal[0]*127)+127;
                                        luxel[1]=(normal[1]*127)+127;
                                        luxel[2]=(normal[2]*127)+127;
@@ -2425,7 +2571,7 @@ void IlluminateRawLightmap( int rawLightmapNum )
                        }
                }
        }
-
+       
        /*      -----------------------------------------------------------------
                dirt pass
                ----------------------------------------------------------------- */
@@ -2492,6 +2638,7 @@ void IlluminateRawLightmap( int rawLightmapNum )
                                if( *cluster < 0 ||
                                        (lm->splotchFix && (luxel[ 0 ] <= ambientColor[ 0 ] || luxel[ 1 ] <= ambientColor[ 1 ] || luxel[ 2 ] <= ambientColor[ 2 ])) )
                                        filterColor = qtrue;
+
                                if( deluxemap && lightmapNum == 0 && (*cluster < 0 || filter) )
                                        filterDir = qtrue;
                                
@@ -2619,6 +2766,8 @@ void IlluminateVertexes( int num )
        rawLightmap_t           *lm;
        bspDrawVert_t           *verts;
        trace_t                         trace;
+       float                           floodLightAmount;
+       vec3_t                          floodColor;
        
        
        /* get surface, info, and raw lightmap */
@@ -2696,11 +2845,20 @@ void IlluminateVertexes( int num )
                                        VectorCopy( verts[ i ].normal, trace.normal );
                                        
                                        /* r7 dirt */
-                                       if( dirty )
+                                       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 );
                                        
@@ -2709,6 +2867,9 @@ void IlluminateVertexes( int num )
                                        {
                                                /* r7 dirt */
                                                VectorScale( colors[ lightmapNum ], dirt, colors[ lightmapNum ] );
+
+                                               /* jal: floodlight */
+                                               VectorAdd( colors[ lightmapNum ], floodColor, colors[ lightmapNum ] ); 
                                                
                                                /* store */
                                                radVertLuxel = RAD_VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
@@ -2724,16 +2885,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);
                                                                
@@ -2746,6 +2907,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 );
@@ -2755,6 +2931,9 @@ void IlluminateVertexes( int num )
                                                                {
                                                                        /* r7 dirt */
                                                                        VectorScale( colors[ lightmapNum ], dirt, colors[ lightmapNum ] );
+
+                                                                       /* jal: floodlight */
+                                                                       VectorAdd( colors[ lightmapNum ], floodColor, colors[ lightmapNum ] ); 
                                                                        
                                                                        /* store */
                                                                        radVertLuxel = RAD_VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
@@ -2965,9 +3144,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;
@@ -2996,23 +3176,27 @@ 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;
                }
+
+       Sys_FPrintf( SYS_VRB, "flags: %d (all: %d)\n", compileFlags, allCompileFlags );
                
                /* 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++;
@@ -3023,6 +3207,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);
+}
 
 
 
@@ -3033,7 +3221,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;
        
        
@@ -3050,7 +3238,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);
        
@@ -3354,7 +3542,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 ];
        
@@ -3467,6 +3655,7 @@ void SetupEnvelopes( qboolean forGrid, qboolean fastFlag )
                                        /* 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
                                {
@@ -3844,7 +4033,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" );
@@ -3878,8 +4067,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;
@@ -3892,9 +4082,11 @@ void SetupFloodLight( void )
 
                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" );
@@ -3908,24 +4100,145 @@ void SetupFloodLight( void )
        VectorNormalize(floodlightRGB,floodlightRGB);
 }
 
-//27 - lighttracer style ambient occlusion light hack.
-//Kudos to the dirtmapping author for most of this source.
-void FloodLightRawLightmap( int rawLightmapNum )
+/*
+FloodLightForSample()
+calculates floodlight value for a given sample
+once again, kudos to the dirtmapping coder
+*/
+
+float FloodLightForSample( trace_t *trace , float floodLightDistance, qboolean floodLightLowQuality)
 {
-       int                                     i, x, y, sx, sy, *cluster;
-       float                           *origin, *normal, *floodlight, *floodlight2, average, samples;
-       rawLightmap_t           *lm;
-       surfaceInfo_t           *info;
-       trace_t                         trace;
+       int             i;
+       float   d;
+       float   contribution;
+       int     sub = 0;
+       float   gatherLight, outLight;
+       vec3_t  normal, worldUp, myUp, myRt, direction, displacement;
+       float   dd;
+       int     vecs = 0;
+       gatherLight=0;
+       /* dummy check */
+       //if( !dirty )
+       //      return 1.0f;
+       if( trace == NULL || trace->cluster < 0 )
+               return 0.0f;
+       
 
-       /* bail if this number exceeds the number of raw lightmaps */
-       if( rawLightmapNum >= numRawLightmaps )
-               return;
+       /* setup */
+       dd = floodLightDistance;
+       VectorCopy( trace->normal, normal );
+       
+       /* check if the normal is aligned to the world-up */
+       if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f && ( normal[ 2 ] == 1.0f || normal[ 2 ] == -1.0f ) )
+       {
+               if( normal[ 2 ] == 1.0f )               
+               {
+                       VectorSet( myRt, 1.0f, 0.0f, 0.0f );
+                       VectorSet( myUp, 0.0f, 1.0f, 0.0f );
+               }
+               else if( normal[ 2 ] == -1.0f )
+               {
+                       VectorSet( myRt, -1.0f, 0.0f, 0.0f );
+                       VectorSet( myUp,  0.0f, 1.0f, 0.0f );
+               }
+       }
+       else
+       {
+               VectorSet( worldUp, 0.0f, 0.0f, 1.0f );
+               CrossProduct( normal, worldUp, myRt );
+               VectorNormalize( myRt, myRt );
+               CrossProduct( myRt, normal, myUp );
+               VectorNormalize( myUp, myUp );
+       }
 
-       /* get lightmap */
-       lm = &rawLightmaps[ rawLightmapNum ];
+       /* vortex: optimise floodLightLowQuality a bit */
+       if ( floodLightLowQuality == qtrue )
+    {
+               /* iterate through ordered vectors */
+               for( i = 0; i < numFloodVectors; i++ )
+                       if (rand()%10 != 0 ) continue;
+       }
+       else
+       {
+               /* iterate through ordered vectors */
+               for( i = 0; i < numFloodVectors; i++ )
+               {
+                       vecs++;
+                
+                       /* transform vector into tangent space */
+                       direction[ 0 ] = myRt[ 0 ] * floodVectors[ i ][ 0 ] + myUp[ 0 ] * floodVectors[ i ][ 1 ] + normal[ 0 ] * floodVectors[ i ][ 2 ];
+                       direction[ 1 ] = myRt[ 1 ] * floodVectors[ i ][ 0 ] + myUp[ 1 ] * floodVectors[ i ][ 1 ] + normal[ 1 ] * floodVectors[ i ][ 2 ];
+                       direction[ 2 ] = myRt[ 2 ] * floodVectors[ i ][ 0 ] + myUp[ 2 ] * floodVectors[ i ][ 1 ] + normal[ 2 ] * floodVectors[ i ][ 2 ];
+
+                       /* set endpoint */
+                       VectorMA( trace->origin, dd, direction, trace->end );
+
+                       //VectorMA( trace->origin, 1, direction, trace->origin );
+                               
+                       SetupTrace( trace );
+                       /* trace */
+                       TraceLine( trace );
+                       contribution=1;
+
+                       if ( trace->compileFlags & C_SKY || trace->compileFlags & C_TRANSLUCENT )
+                       {
+                               contribution=1.0f;
+                       }
+                       else if ( trace->opaque )
+                       {
+                               VectorSubtract( trace->hit, trace->origin, displacement );
+                               d=VectorLength( displacement );
+
+                               // d=trace->distance;            
+                               //if (d>256) gatherDirt+=1;
+                               contribution=d/dd;
+                               if (contribution>1) contribution=1.0f; 
+                    
+                               //gatherDirt += 1.0f - ooDepth * VectorLength( displacement );
+                       }
+                
+                       gatherLight+=contribution;
+               }
+       }
+   
+       /* early out */
+       if( gatherLight <= 0.0f )
+               return 0.0f;
+       
+       sub=vecs;
+
+       if (sub<1) sub=1;
+       gatherLight/=(sub);
 
+       outLight=gatherLight;
+       if( outLight > 1.0f )
+               outLight = 1.0f;
+       
+       /* return to sender */
+       return outLight;
+}
+
+/*
+FloodLightRawLightmap
+lighttracer style ambient occlusion light hack.
+Kudos to the dirtmapping author for most of this source.
+VorteX: modified to floodlight up custom surfaces (q3map_floodLight)
+VorteX: fixed problems with deluxemapping
+*/
+
+// floodlight pass on a lightmap
+void FloodLightRawLightmapPass( rawLightmap_t *lm , vec3_t lmFloodLightRGB, float lmFloodLightIntensity, float lmFloodLightDistance, qboolean lmFloodLightLowQuality, float floodlightDirectionScale)
+{
+       int                                     i, x, y, *cluster;
+       float                           *origin, *normal, *floodlight, floodLightAmount;
+       surfaceInfo_t           *info;
+       trace_t                         trace;
+       // int sx, sy;
+       // float samples, average, *floodlight2;
+       
        memset(&trace,0,sizeof(trace_t));
+
        /* setup trace */
        trace.testOcclusion = qtrue;
        trace.forceSunlight = qfalse;
@@ -3936,14 +4249,14 @@ void FloodLightRawLightmap( int rawLightmapNum )
        trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
        trace.testAll = qfalse;
        trace.distance = 1024;
-
+       
        /* twosided lighting (may or may not be a good idea for lightmapped stuff) */
        //trace.twoSided = qfalse;
        for( i = 0; i < trace.numSurfaces; i++ )
        {
                /* get surface */
                info = &surfaceInfos[ trace.surfaces[ i ] ];
-
+               
                /* check twosidedness */
                if( info->si->twoSided )
                {
@@ -3951,8 +4264,8 @@ void FloodLightRawLightmap( int rawLightmapNum )
                        break;
                }
        }
-
-       /* gather dirt */
+       
+       /* gather floodlight */
        for( y = 0; y < lm->sh; y++ )
        {
                for( x = 0; x < lm->sw; x++ )
@@ -3962,29 +4275,35 @@ void FloodLightRawLightmap( int rawLightmapNum )
                        origin = SUPER_ORIGIN( x, y );
                        normal = SUPER_NORMAL( x, y );
                        floodlight = SUPER_FLOODLIGHT( x, y );
-
+                       
                        /* set default dirt */
                        *floodlight = 0.0f;
-
+                       
                        /* only look at mapped luxels */
                        if( *cluster < 0 )
                                continue;
-
+                       
                        /* copy to trace */
                        trace.cluster = *cluster;
                        VectorCopy( origin, trace.origin );
                        VectorCopy( normal, trace.normal );
-
-
-
-                       /* get dirt */
-                       *floodlight = FloodLightForSample( &trace );
+   
+                       /* get floodlight */
+                       floodLightAmount = FloodLightForSample( &trace , lmFloodLightDistance, lmFloodLightLowQuality)*lmFloodLightIntensity;
+                       
+                       /* add floodlight */
+                       floodlight[0] += lmFloodLightRGB[0]*floodLightAmount;
+                       floodlight[1] += lmFloodLightRGB[1]*floodLightAmount;
+                       floodlight[2] += lmFloodLightRGB[2]*floodLightAmount;
+                       floodlight[3] += floodlightDirectionScale;
                }
        }
-
+       
        /* testing no filtering */
        return;
 
+#if 0
+       
        /* filter "dirt" */
        for( y = 0; y < lm->sh; y++ )
        {
@@ -3992,8 +4311,8 @@ void FloodLightRawLightmap( int rawLightmapNum )
                {
                        /* get luxel */
                        cluster = SUPER_CLUSTER( x, y );
-                       floodlight = SUPER_FLOODLIGHT( x, y );
-
+                       floodlight = SUPER_FLOODLIGHT(x, y );
+                       
                        /* filter dirt by adjacency to unmapped luxels */
                        average = *floodlight;
                        samples = 1.0f;
@@ -4001,148 +4320,132 @@ void FloodLightRawLightmap( int rawLightmapNum )
                        {
                                if( sy < 0 || sy >= lm->sh )
                                        continue;
-
+                               
                                for( sx = (x - 1); sx <= (x + 1); sx++ )
                                {
                                        if( sx < 0 || sx >= lm->sw || (sx == x && sy == y) )
                                                continue;
-
+                                       
                                        /* get neighboring luxel */
                                        cluster = SUPER_CLUSTER( sx, sy );
                                        floodlight2 = SUPER_FLOODLIGHT( sx, sy );
                                        if( *cluster < 0 || *floodlight2 <= 0.0f )
                                                continue;
-
+                                       
                                        /* add it */
                                        average += *floodlight2;
                                        samples += 1.0f;
                                }
-
+                               
                                /* bail */
                                if( samples <= 0.0f )
                                        break;
                        }
-
+                       
                        /* bail */
                        if( samples <= 0.0f )
                                continue;
-
+                       
                        /* scale dirt */
                        *floodlight = average / samples;
                }
        }
+#endif
 }
 
-/*
-FloodLightForSample()
-calculates floodlight value for a given sample
-once again, kudos to the dirtmapping coder
-*/
-float FloodLightForSample( trace_t *trace )
+void FloodLightRawLightmap( int rawLightmapNum )
 {
-       int             i;
-       float   d;
-       float   contribution;
-       int     sub = 0;
-       float   gatherLight, outLight;
-       vec3_t  normal, worldUp, myUp, myRt, direction, displacement;
-       float   dd;
-       int     vecs = 0;
-
-       gatherLight=0;
-       /* dummy check */
-       //if( !dirty )
-       //      return 1.0f;
-       if( trace == NULL || trace->cluster < 0 )
-               return 0.0f;
+       rawLightmap_t           *lm;
 
+       /* bail if this number exceeds the number of raw lightmaps */
+       if( rawLightmapNum >= numRawLightmaps )
+               return;
+       /* get lightmap */
+       lm = &rawLightmaps[ rawLightmapNum ];
 
-       /* setup */
-       dd = floodlightDistance;
-       VectorCopy( trace->normal, normal );
+       /* global pass */
+       if (floodlighty && floodlightIntensity)
+               FloodLightRawLightmapPass(lm, floodlightRGB, floodlightIntensity, floodlightDistance, floodlight_lowquality, floodlightDirectionScale);
 
-       /* check if the normal is aligned to the world-up */
-       if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f )
+       /* custom pass */
+       if (lm->floodlightIntensity)
        {
-               if( normal[ 2 ] == 1.0f )
-               {
-                       VectorSet( myRt, 1.0f, 0.0f, 0.0f );
-                       VectorSet( myUp, 0.0f, 1.0f, 0.0f );
-               }
-               else if( normal[ 2 ] == -1.0f )
-               {
-                       VectorSet( myRt, -1.0f, 0.0f, 0.0f );
-                       VectorSet( myUp,  0.0f, 1.0f, 0.0f );
-               }
-       }
-       else
-       {
-               VectorSet( worldUp, 0.0f, 0.0f, 1.0f );
-               CrossProduct( normal, worldUp, myRt );
-               VectorNormalize( myRt, myRt );
-               CrossProduct( myRt, normal, myUp );
-               VectorNormalize( myUp, myUp );
+               FloodLightRawLightmapPass(lm, lm->floodlightRGB, lm->floodlightIntensity, lm->floodlightDistance, qfalse, lm->floodlightDirectionScale);
+               numSurfacesFloodlighten += 1;
        }
+}
 
-       /* iterate through ordered vectors */
-       for( i = 0; i < numFloodVectors; i++ )
-       {
-               if (floodlight_lowquality==qtrue)
-        {
-                       if (rand()%10 != 0 ) continue;
-               }
-
-               vecs++;
-
-               /* transform vector into tangent space */
-               direction[ 0 ] = myRt[ 0 ] * floodVectors[ i ][ 0 ] + myUp[ 0 ] * floodVectors[ i ][ 1 ] + normal[ 0 ] * floodVectors[ i ][ 2 ];
-               direction[ 1 ] = myRt[ 1 ] * floodVectors[ i ][ 0 ] + myUp[ 1 ] * floodVectors[ i ][ 1 ] + normal[ 1 ] * floodVectors[ i ][ 2 ];
-               direction[ 2 ] = myRt[ 2 ] * floodVectors[ i ][ 0 ] + myUp[ 2 ] * floodVectors[ i ][ 1 ] + normal[ 2 ] * floodVectors[ i ][ 2 ];
+void FloodlightRawLightmaps()
+{
+       Sys_Printf( "--- FloodlightRawLightmap ---\n" );
+       numSurfacesFloodlighten = 0;
+       RunThreadsOnIndividual( numRawLightmaps, qtrue, FloodLightRawLightmap );
+       Sys_Printf( "%9d custom lightmaps floodlighted\n", numSurfacesFloodlighten );
+}
 
-               /* set endpoint */
-               VectorMA( trace->origin, dd, direction, trace->end );
+/*
+FloodLightIlluminate()
+illuminate floodlight into lightmap luxels
+*/
 
-               //VectorMA( trace->origin, 1, direction, trace->origin );
+void FloodlightIlluminateLightmap( rawLightmap_t *lm )
+{
+       float                           *luxel, *floodlight, *deluxel, *normal;
+       int                                     *cluster;
+       float                           brightness;
+       int                                     x, y, lightmapNum;
 
-               SetupTrace( trace );
-               /* trace */
-               TraceLine( trace );
-               contribution=1;
+       /* walk lightmaps */
+       for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+       {
+               /* early out */
+               if( lm->superLuxels[ lightmapNum ] == NULL )
+                       continue;
 
-               if (trace->compileFlags & C_SKY )
-               {
-                       contribution=1.0f;
-               }
-               else if ( trace->opaque )
+               /* apply floodlight to each luxel */
+               for( y = 0; y < lm->sh; y++ )
                {
-                       VectorSubtract( trace->hit, trace->origin, displacement );
-                       d=VectorLength( displacement );
+                       for( x = 0; x < lm->sw; x++ )
+                       {
+                               /* get floodlight */
+                               floodlight = SUPER_FLOODLIGHT( x, y );
+                               if (!floodlight[0] && !floodlight[1] && !floodlight[2])
+                                       continue;
+                                               
+                               /* get cluster */
+                               cluster = SUPER_CLUSTER( x, y );
 
-                       // d=trace->distance;
-                       //if (d>256) gatherDirt+=1;
-                       contribution=d/dd;
-                       if (contribution>1) contribution=1.0f;
+                               /* only process mapped luxels */
+                               if( *cluster < 0 )
+                                       continue;
 
-                       //gatherDirt += 1.0f - ooDepth * VectorLength( displacement );
-               }
+                               /* get particulars */
+                               luxel = SUPER_LUXEL( lightmapNum, x, y );
+                               deluxel = SUPER_DELUXEL( x, y );
 
-               gatherLight+=contribution;
-       }
+                               /* add to lightmap */
+                               luxel[0]+=floodlight[0];
+                               luxel[1]+=floodlight[1];
+                               luxel[2]+=floodlight[2];
 
-       /* early out */
-       if( gatherLight <= 0.0f )
-               return 0.0f;
+                               if (luxel[3]==0) luxel[3]=1;
 
-       sub=vecs;
+                               /* add to deluxemap */
+                               if (deluxemap && floodlight[3] > 0)
+                               {
+                                       vec3_t                          lightvector;
 
-       if (sub<1) sub=1;
-       gatherLight/=(sub);
+                                       normal = SUPER_NORMAL( x, y );
+                                       brightness = RGBTOGRAY( floodlight ) * ( 1.0f/255.0f ) * floodlight[3];
 
-       outLight=gatherLight;
-       if( outLight > 1.0f )
-               outLight = 1.0f;
+                                       // 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;
 
-       /* return to sender */
-       return outLight;
+                                       VectorScale( normal, brightness, lightvector );
+                                       VectorAdd( deluxel, lightvector, deluxel );
+                               }
+                       }
+               }
+       }
 }
-