Exemplo n.º 1
0
static void ComputeLightmapColorFromAverage( dface_t* pFace, directlight_t* pSkylight, float scale, Vector pColor[MAX_LIGHTSTYLES] )
{
	texinfo_t* pTex = &texinfo[pFace->texinfo];
	if (pTex->flags & SURF_SKY)
	{
		if (pSkylight)
		{
			// add in sky ambient
			Vector amb = pSkylight->light.intensity / 255.0f; 
			pColor[0] += amb * scale;
		}
		return;
	}

	for (int maps = 0 ; maps < MAXLIGHTMAPS && pFace->styles[maps] != 255 ; ++maps)
	{
		ColorRGBExp32* pAvgColor = dface_AvgLightColor( pFace, maps );

		// this code expects values from [0..1] not [0..255]
		Vector color;
		color[0] = TexLightToLinear( pAvgColor->r, pAvgColor->exponent );
		color[1] = TexLightToLinear( pAvgColor->g, pAvgColor->exponent );
		color[2] = TexLightToLinear( pAvgColor->b, pAvgColor->exponent );

		ComputeAmbientFromSurface( pFace, pSkylight, color );

		int style = pFace->styles[maps];
		pColor[style] += color * scale;
	}
}
Exemplo n.º 2
0
//-----------------------------------------------------------------------------
// Trace hemispherical rays from a vertex, accumulating indirect
// sources at each ray termination.
//-----------------------------------------------------------------------------
void ComputeIndirectLightingAtPoint( Vector &position, Vector &normal, Vector &outColor,
									 int iThread, bool force_fast, bool bIgnoreNormals )
{
	Ray_t			ray;
	CLightSurface	surfEnum(iThread);

	outColor.Init();

	
	int nSamples = NUMVERTEXNORMALS;
	if ( do_fast || force_fast )
		nSamples /= 4;
	else
		nSamples *= g_flSkySampleScale;

	float totalDot = 0;
	DirectionalSampler_t sampler;
	for (int j = 0; j < nSamples; j++)
	{
		Vector samplingNormal = sampler.NextValue();
		float dot;

		if ( bIgnoreNormals )
			dot = (0.7071/2);
		else
			dot = DotProduct( normal, samplingNormal );

		if ( dot <= EQUAL_EPSILON )
		{
			// reject angles behind our plane
			continue;
		}

		totalDot += dot;

		// trace to determine surface
		Vector vEnd;
		VectorScale( samplingNormal, MAX_TRACE_LENGTH, vEnd );
		VectorAdd( position, vEnd, vEnd );

		ray.Init( position, vEnd, vec3_origin, vec3_origin );
		if ( !surfEnum.FindIntersection( ray ) )
			continue;

		// get color from surface lightmap
		texinfo_t* pTex = &texinfo[surfEnum.m_pSurface->texinfo];
		if ( !pTex || pTex->flags & SURF_SKY )
		{
			// ignore contribution from sky
			// sky ambient already accounted for during direct pass
			continue;
		}

		if ( surfEnum.m_pSurface->styles[0] == 255 || surfEnum.m_pSurface->lightofs < 0 )
		{
			// no light affects this face
			continue;
		}


		Vector lightmapColor;
		if ( !surfEnum.m_bHasLuxel )
		{
			ColorRGBExp32* pAvgLightmapColor = dface_AvgLightColor( surfEnum.m_pSurface, 0 );
			ColorRGBExp32ToVector( *pAvgLightmapColor, lightmapColor );
		}
		else
		{
			// get color from displacement
			int smax = ( surfEnum.m_pSurface->m_LightmapTextureSizeInLuxels[0] ) + 1;
			int tmax = ( surfEnum.m_pSurface->m_LightmapTextureSizeInLuxels[1] ) + 1;

			// luxelcoord is in the space of the accumulated lightmap page; we need to convert
			// it to be in the space of the surface
			int ds = clamp( (int)surfEnum.m_LuxelCoord.x, 0, smax-1 );
			int dt = clamp( (int)surfEnum.m_LuxelCoord.y, 0, tmax-1 );

			ColorRGBExp32* pLightmap = (ColorRGBExp32*)&(*pdlightdata)[surfEnum.m_pSurface->lightofs];
			pLightmap += dt * smax + ds;
			ColorRGBExp32ToVector( *pLightmap, lightmapColor );
		}

		VectorMultiply( lightmapColor, dtexdata[pTex->texdata].reflectivity, lightmapColor );
		VectorAdd( outColor, lightmapColor, outColor );
	}

	if ( totalDot )
	{
		VectorScale( outColor, 1.0f/totalDot, outColor );
	}
}
Exemplo n.º 3
0
/*
=============
FinalLightFace

Add the indirect lighting on top of the direct
lighting and save into final map format
=============
*/
void FinalLightFace( int iThread, int facenum )
{
	dface_t	        *f;
	int		        i, j, k;
	facelight_t	    *fl;
	float		    minlight;
	int			    lightstyles;
	LightingValue_t lb[NUM_BUMP_VECTS + 1], v[NUM_BUMP_VECTS + 1];
	unsigned char   *pdata[NUM_BUMP_VECTS + 1];
	int				bumpSample;
	radial_t	    *rad = NULL;
	radial_t	    *prad = NULL;

   	f = &g_pFaces[facenum];

    // test for non-lit texture
    if ( texinfo[f->texinfo].flags & TEX_SPECIAL)
        return;		

	fl = &facelight[facenum];


	for (lightstyles=0; lightstyles < MAXLIGHTMAPS; lightstyles++ )
	{
		if ( f->styles[lightstyles] == 255 )
			break;
	}
	if ( !lightstyles )
		return;

	
	//
	// sample the triangulation
	//
	minlight = FloatForKey (face_entity[facenum], "_minlight") * 128;

	bool needsBumpmap = ( texinfo[f->texinfo].flags & SURF_BUMPLIGHT ) ? true : false;
	int bumpSampleCount = needsBumpmap ? NUM_BUMP_VECTS + 1 : 1;

	bool bDisp = ( f->dispinfo != -1 );

//#define RANDOM_COLOR

#ifdef RANDOM_COLOR
	unsigned char randomColor[3];
	GetRandomColor( randomColor );
#endif
	

	// NOTE: I'm using these RB trees to sort all the illumination values
	// to compute median colors. Turns out that this is a somewhat better
	// method that using the average; usually if there are surfaces
	// with a large light intensity variation, the extremely bright regions
	// have a very small area and tend to influence the average too much.
	CUtlRBTree< float, int >	m_Red( 0, 256, FloatLess );
	CUtlRBTree< float, int >	m_Green( 0, 256, FloatLess );
	CUtlRBTree< float, int >	m_Blue( 0, 256, FloatLess );

	for (k=0 ; k < lightstyles; k++ )
	{
		m_Red.RemoveAll();
		m_Green.RemoveAll();
		m_Blue.RemoveAll();

		if (!do_fast)
		{
			if( !bDisp )
			{
				rad = BuildLuxelRadial( facenum, k );
			}
			else
			{
				rad = StaticDispMgr()->BuildLuxelRadial( facenum, k, needsBumpmap );
			}
		}

		if (numbounce > 0 && k == 0)
		{
			// currently only radiosity light non-displacement surfaces!
			if( !bDisp )
			{
				prad = BuildPatchRadial( facenum );
			}
			else
			{
				prad = StaticDispMgr()->BuildPatchRadial( facenum, needsBumpmap );
			}
		}

		// pack the nonbump texture and the three bump texture for the given 
		// lightstyle right next to each other.
		// NOTE: Even though it's building positions for all bump-mapped data,
		// it isn't going to use those positions (see loop over bumpSample below)
		// The file offset is correctly computed to only store space for 1 set
		// of light data if we don't have bumped lighting.
		for( bumpSample = 0; bumpSample < bumpSampleCount; ++bumpSample )
		{
			pdata[bumpSample] = &(*pdlightdata)[f->lightofs + (k * bumpSampleCount + bumpSample) * fl->numluxels*4]; 
		}

		// Compute the average luxel color, but not for the bump samples
		Vector avg( 0.0f, 0.0f, 0.0f );
		int avgCount = 0;

		for (j=0 ; j<fl->numluxels; j++)
		{
			// garymct - direct lighting
			bool baseSampleOk = true;

			if (!do_fast)
			{
				if( !bDisp )
				{
					baseSampleOk = SampleRadial( rad, fl->luxel[j], lb, bumpSampleCount );
				}
				else
				{
					baseSampleOk = StaticDispMgr()->SampleRadial( facenum, rad, fl->luxel[j], j, lb, bumpSampleCount, false );
				}
			}
			else
			{
				for ( int iBump = 0 ; iBump < bumpSampleCount; iBump++ )
				{
					lb[iBump] = fl->light[0][iBump][j];
				}
			}

			if (prad)
			{
				// garymct - bounced light
				// v is indirect light that is received on the luxel.
				if( !bDisp )
				{
					SampleRadial( prad, fl->luxel[j], v, bumpSampleCount );
				}
				else
				{
					StaticDispMgr()->SampleRadial( facenum, prad, fl->luxel[j], j, v, bumpSampleCount, true );
				}

				for( bumpSample = 0; bumpSample < bumpSampleCount; ++bumpSample )
				{
					lb[bumpSample].AddLight( v[bumpSample] );
				}
			}

			if ( bDisp && g_bDumpPatches )
			{
				for( bumpSample = 0; bumpSample < bumpSampleCount; ++bumpSample )
				{
					DumpDispLuxels( facenum, lb[bumpSample].m_vecLighting, j, bumpSample );
				}
			}

			if (fl->numsamples == 0)
			{
				for( i = 0; i < bumpSampleCount; i++ )
				{
					lb[i].Init( 255, 0, 0 );
				}
				baseSampleOk = false;
			}

			int bumpSample;
			for( bumpSample = 0; bumpSample < bumpSampleCount; bumpSample++ )
			{
				// clip from the bottom first
				// garymct: minlight is a per entity minimum light value?
				for( i=0; i<3; i++ )
				{
					lb[bumpSample].m_vecLighting[i] = max( lb[bumpSample].m_vecLighting[i], minlight );
				}
				
				// Do the average light computation, I'm assuming (perhaps incorrectly?)
				// that all luxels in a particular lightmap have the same area here. 
				// Also, don't bother doing averages for the bump samples. Doing it here 
				// because of the minlight clamp above + the random color testy thingy. 
				// Also have to do it before Vec3toColorRGBExp32 because it 
				// destructively modifies lb[bumpSample] (Feh!)
				if ((bumpSample == 0) && baseSampleOk)
				{
					++avgCount;

					ApplyMacroTextures( facenum, fl->luxel[j], lb[0].m_vecLighting );

					// For median computation
					m_Red.Insert( lb[bumpSample].m_vecLighting[0] );
					m_Green.Insert( lb[bumpSample].m_vecLighting[1] );
					m_Blue.Insert( lb[bumpSample].m_vecLighting[2] );
				}

#ifdef RANDOM_COLOR
				pdata[bumpSample][0] = randomColor[0] / ( bumpSample + 1 );
				pdata[bumpSample][1] = randomColor[1] / ( bumpSample + 1 );
				pdata[bumpSample][2] = randomColor[2] / ( bumpSample + 1 );
				pdata[bumpSample][3] = 0;
#else
				// convert to a 4 byte r,g,b,signed exponent format
				VectorToColorRGBExp32( Vector( lb[bumpSample].m_vecLighting.x, lb[bumpSample].m_vecLighting.y,
											   lb[bumpSample].m_vecLighting.z ), *( ColorRGBExp32 *)pdata[bumpSample] );
#endif

				pdata[bumpSample] += 4;
			}
		}
		FreeRadial( rad );
		if (prad)
		{
			FreeRadial( prad );
			prad = NULL;
		}

		// Compute the median color for this lightstyle
		// Remember, the data goes *before* the specified light_ofs, in *reverse order*
		ColorRGBExp32 *pAvgColor = dface_AvgLightColor( f, k );
		if (avgCount == 0)
		{
			Vector median( 0, 0, 0 );
			VectorToColorRGBExp32( median, *pAvgColor );
		}
		else
		{
			unsigned int r, g, b;
			r = m_Red.FirstInorder();
			g = m_Green.FirstInorder();
			b = m_Blue.FirstInorder();
			avgCount >>= 1;
			while (avgCount > 0)
			{
				r = m_Red.NextInorder(r);
				g = m_Green.NextInorder(g);
				b = m_Blue.NextInorder(b);
				--avgCount;
			}

			Vector median( m_Red[r], m_Green[g], m_Blue[b] );
			VectorToColorRGBExp32( median, *pAvgColor );
		}
	}
}