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 )
{
rawLightmap_t *lm;
surfaceInfo_t *info;
trace_t trace;
-
+ qboolean noDirty;
+
/* bail if this number exceeds the number of raw lightmaps */
if( rawLightmapNum >= numRawLightmaps )
trace.numSurfaces = lm->numLightSurfaces;
trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
- trace.testAll = qfalse;
+ trace.testAll = qtrue;
/* twosided lighting (may or may not be a good idea for lightmapped stuff) */
trace.twoSided = qfalse;
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++ )
/* 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;
/* 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( 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 ] );
}
}
qboolean filterColor, filterDir;
float brightness;
float *origin, *normal, *dirt, *luxel, *luxel2, *deluxel, *deluxel2;
+ unsigned char *flag;
float *lightLuxels, *lightLuxel, samples, filterRadius, weight;
vec3_t color, 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 */
VectorCopy( ambientColor, luxel );
if( deluxemap )
{
- VectorScale( normal, 0.00390625f, deluxel );
- deluxel[3] = 0.00390625f;
+ 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;
}
memset( lightLuxels, 0, llSize );
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 && 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++ )
{
deluxel = SUPER_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 ////
LightContributionToSample( &trace );
VectorCopy( trace.color, lightLuxel );
+ /* add the contribution to the deluxemap */
+ if( deluxemap )
+ VectorAdd( deluxel, trace.directionContribution, deluxel );
+
+ /* check for evilness */
+ if(trace.forceSubsampling > 1.0f && lightSamples > 1 && 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++;
}
-
- /* add to light direction map (fixme: use luxel normal as starting point for deluxel?) */
- if( deluxemap )
- {
- /* 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, temp );
- VectorAdd( deluxel, temp, deluxel );
- deluxel[3] += brightness;
- }
}
}
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 )
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 )
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 );
origin = SUPER_ORIGIN( sx, sy );
//% continue;
/* subsample it */
- SubsampleRawLuxel_r( lm, &trace, origin, sx, sy, 0.25f, lightLuxel );
+ SubsampleRawLuxel_r( lm, &trace, origin, sx, sy, 0.25f * lightSamplesSearchBoxSize, lightLuxel );
+
+ *flag |= FLAG_ALREADY_SUBSAMPLED;
/* debug code to colorize subsampled areas to yellow */
//% luxel = SUPER_LUXEL( lightmapNum, sx, sy );
lm->superLuxels[ lightmapNum ] = safe_malloc( size );
memset( lm->superLuxels[ lightmapNum ], 0, size );
}
-
+
/* set style */
if( lightmapNum > 0 )
{
/* 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;
- }
- }
- }
- }
+ FloodlightIlluminateLightmap(lm);
if (debugnormals)
{
/* early out */
if( lm->superLuxels[ lightmapNum ] == NULL )
continue;
-
+
for( y = 0; y < lm->sh; y++ )
{
for( x = 0; x < lm->sw; x++ )
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;
}
}
}
-
+
/* -----------------------------------------------------------------
dirt pass
----------------------------------------------------------------- */
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;
rawLightmap_t *lm;
bspDrawVert_t *verts;
trace_t trace;
+ float floodLightAmount;
+ vec3_t floodColor;
/* get surface, info, and raw lightmap */
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 );
{
/* 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 );
{
/* 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 );
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 )
+ {
+ 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;
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 )
{
break;
}
}
-
- /* gather dirt */
+
+ /* gather floodlight */
for( y = 0; y < lm->sh; y++ )
{
for( x = 0; x < lm->sw; x++ )
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++ )
{
{
/* 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;
{
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, 1.0f);
- /* 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 );
+ }
+ }
+ }
+ }
}
-