Example #1
0
void RayTracingEnvironment::RenderScene(
	int width, int height,								   // width and height of desired rendering
	int stride,											 // actual width in pixels of target buffer
	uint32 *output_buffer,									// pointer to destination 
	Vector CameraOrigin,									// eye position
	Vector ULCorner,										// word space coordinates of upper left
															// monitor corner
	Vector URCorner,										// top right corner
	Vector LLCorner,										// lower left
	Vector LRCorner,										// lower right
	RayTraceLightingMode_t lmode)
{
	// first, compute deltas
	Vector dxvector=URCorner;
	dxvector-=ULCorner;
	dxvector*=(1.0/width);
	Vector dxvectortimes2=dxvector;
	dxvectortimes2+=dxvector;

	Vector dyvector=LLCorner;
	dyvector-=ULCorner;
	dyvector*=(1.0/height);


	// block_offsets-relative offsets for eahc of the 4 pixels in the block, in sse format
	FourVectors block_offsets;
	block_offsets.LoadAndSwizzle(Vector(0,0,0),dxvector,dyvector,dxvector+dyvector);
	
	FourRays myrays;
	myrays.origin.DuplicateVector(CameraOrigin);
	
	// tmprays is used fo rthe case when we cannot trace 4 rays at once.
	FourRays tmprays;
	tmprays.origin.DuplicateVector(CameraOrigin);

	// now, we will ray trace pixels. we will do the rays in a 2x2 pattern
	for(int y=0;y<height;y+=2)
	{
		Vector SLoc=dyvector;
		SLoc*=((float) y);
		SLoc+=ULCorner;
		uint32 *dest=output_buffer+y*stride;
		for(int x=0;x<width;x+=2)
		{
			myrays.direction.DuplicateVector(SLoc);
			myrays.direction+=block_offsets;
			myrays.direction.VectorNormalize();
			
			RayTracingResult rslt;
			Trace4Rays(myrays,all_zeros,TraceLimit, &rslt);
			if ((rslt.HitIds[0]==-1) && (rslt.HitIds[1]==-1) && 
				(rslt.HitIds[2]==-1) && (rslt.HitIds[3]==-1))
				MapLinearIntensities(BackgroundColor,dest,dest+1,dest+stride,dest+stride+1);
			else
			{
				// make sure normal points back towards ray origin
				fltx4 ndoti=rslt.surface_normal*myrays.direction;
				fltx4 bad_dirs=AndSIMD(CmpGtSIMD(ndoti,Four_Zeros),
										   LoadAlignedSIMD((float *) signmask));

				// flip signs of all "wrong" normals
				rslt.surface_normal.x=XorSIMD(bad_dirs,rslt.surface_normal.x);
				rslt.surface_normal.y=XorSIMD(bad_dirs,rslt.surface_normal.y);
				rslt.surface_normal.z=XorSIMD(bad_dirs,rslt.surface_normal.z);

				FourVectors intens;
				intens.DuplicateVector(Vector(0,0,0));
				// set up colors
				FourVectors surf_colors;
				surf_colors.DuplicateVector(Vector(0,0,0));
				for(int i=0;i<4;i++)
				{
					if (rslt.HitIds[i]>=0)
					{
						surf_colors.X(i)=TriangleColors[rslt.HitIds[i]].x;
						surf_colors.Y(i)=TriangleColors[rslt.HitIds[i]].y;
						surf_colors.Z(i)=TriangleColors[rslt.HitIds[i]].z;
					}

				}
				FourVectors surface_pos=myrays.direction;
				surface_pos*=rslt.HitDistance;
				surface_pos+=myrays.origin;
				
				switch(lmode)
				{
					case DIRECT_LIGHTING:
					{
						// light all points
						for(int l=0;l<LightList.Count();l++)
						{
							LightList[l].ComputeLightAtPoints(surface_pos,rslt.surface_normal,
															  intens);
						}
					}
					break;

					case DIRECT_LIGHTING_WITH_SHADOWS:
					{
						// light all points
						for(int l=0;l<LightList.Count();l++)
						{
							FourVectors ldir;
							ldir.DuplicateVector(LightList[l].m_Position);
							ldir-=surface_pos;
							fltx4 MaxT=ldir.length();
							ldir.VectorNormalizeFast();
							// now, compute shadow flag
							FourRays myrays;
							myrays.origin=surface_pos;
							FourVectors epsilon=ldir;
							epsilon*=0.01;
							myrays.origin+=epsilon;
							myrays.direction=ldir;
							RayTracingResult shadowtest;
							Trace4Rays(myrays,Four_Zeros,MaxT, &shadowtest);
							fltx4 unshadowed=CmpGtSIMD(shadowtest.HitDistance,MaxT);
							if (! (IsAllZeros(unshadowed)))
							{
								FourVectors tmp;
								tmp.DuplicateVector(Vector(0,0,0));
								LightList[l].ComputeLightAtPoints(surface_pos,rslt.surface_normal,
																  tmp);
								intens.x=AddSIMD(intens.x,AndSIMD(tmp.x,unshadowed));
								intens.y=AddSIMD(intens.y,AndSIMD(tmp.y,unshadowed));
								intens.z=AddSIMD(intens.z,AndSIMD(tmp.z,unshadowed));
							}
						}
					}
					break;
				}
				// now, mask off non-hitting pixels
				intens.VProduct(surf_colors);
				fltx4 no_hit_mask=CmpGtSIMD(rslt.HitDistance,TraceLimit);
				
				intens.x=OrSIMD(AndSIMD(BackgroundColor.x,no_hit_mask),
								   AndNotSIMD(no_hit_mask,intens.x));
				intens.y=OrSIMD(AndSIMD(BackgroundColor.y,no_hit_mask),
								   AndNotSIMD(no_hit_mask,intens.y));
				intens.z=OrSIMD(AndSIMD(BackgroundColor.y,no_hit_mask),
								   AndNotSIMD(no_hit_mask,intens.z));

				MapLinearIntensities(intens,dest,dest+1,dest+stride,dest+stride+1);
			}
			dest+=2;
			SLoc+=dxvectortimes2;
		}
	}
}
void CLightingManager::SortLights()
{
#if DEBUG
	for ( int i = 0; i < LSORT_COUNT; i++ )
		Assert( m_hPreSortedLights[ i ].Count() == 0 );
#endif

	m_bDrawVolumetrics = false;

	float zNear = m_flzNear + 2;

	Vector vecBloat( zNear, zNear, zNear );

	Vector camMins( m_vecViewOrigin - vecBloat );
	Vector camMaxs( m_vecViewOrigin + vecBloat );

#if DEFCFG_USE_SSE
	fltx4 zNearX4 = ReplicateX4( zNear );

	for( int i = 0; i < m_uiSortDataCount; i++ )
	{
		def_light_presortdatax4_t& s = m_pSortDataX4[i];

		fltx4 adjustedMins[3] = { SubSIMD( s.bounds_min_naive[0], zNearX4 ),
			SubSIMD( s.bounds_min_naive[1], zNearX4 ),
			SubSIMD( s.bounds_min_naive[2], zNearX4 ) };

		fltx4 adjustedMaxs[3] = { AddSIMD( s.bounds_max_naive[0], zNearX4 ),
			AddSIMD( s.bounds_max_naive[1], zNearX4 ),
			AddSIMD( s.bounds_max_naive[2], zNearX4 ) };

		fltx4 needsFullscreen = IsPointInBoundsX4( m_vecViewOrigin,
			adjustedMins, adjustedMaxs );

		//Jack: this is terrible I know
		for( int i = 0; i < s.count; i++ )
		{
			if( s.lights[i]->IsSpot() )
			{
				if( _isnan( SubFloat( needsFullscreen, i ) ) )
				{
					if( !s.lights[i]->spotFrustum.CullBox( camMins, camMaxs ) )
					{
						m_hPreSortedLights[LSORT_SPOT_FULLSCREEN].AddToTail( s.lights[i] );
					}
					else
					{
						m_hPreSortedLights[LSORT_SPOT_WORLD].AddToTail( s.lights[i] );
					}
				}
				else
				{
					m_hPreSortedLights[LSORT_SPOT_WORLD].AddToTail( s.lights[i] );
				}
			}
			else
			{
				if( _isnan( SubFloat( needsFullscreen, i ) ) )
				{
					m_hPreSortedLights[LSORT_POINT_FULLSCREEN].AddToTail( s.lights[i] );
				}
				else
				{
					m_hPreSortedLights[LSORT_POINT_WORLD].AddToTail( s.lights[i] );
				}
			}
		}

		fltx4 volume = AndSIMD( s.hasVolumetrics, s.hasVolumetrics );

		m_bDrawVolumetrics = m_bDrawVolumetrics || !IsAllZeros( volume );
	}
#else
	FOR_EACH_VEC_FAST( def_light_t*, m_hRenderLights, l )
	{
		bool bNeedsFullscreen = IsPointInBounds( m_vecViewOrigin,
			l->bounds_min_naive - vecBloat,
			l->bounds_max_naive + vecBloat );

		if ( bNeedsFullscreen && l->IsSpot() )
		{
			bNeedsFullscreen = !l->spotFrustum.CullBox( camMins, camMaxs );
		}

		const bool bVolume = ( l->HasShadow() && l->HasVolumetrics() );

		m_bDrawVolumetrics = m_bDrawVolumetrics || bVolume;

		Assert( l->iLighttype * 2 + 1 < LSORT_COUNT );
		m_hPreSortedLights[ l->iLighttype * 2 + (int)bNeedsFullscreen ].AddToTail( l );
	}