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 ); }