void MapLinearIntensities(FourVectors const &intens,uint32 *p1, uint32 *p2, uint32 *p3, uint32 *p4) { // convert four pixels worth of sse-style rgb into argb lwords // NOTE the _mm_empty macro is voodoo. do not mess with this routine casually - simply throwing // anything that ends up generating a fpu stack references in here would be bad news. static fltx4 pixscale={255.0,255.0,255.0,255.0}; fltx4 r,g,b; r=MinSIMD(pixscale,MulSIMD(pixscale,PowSIMD(intens.x,IGAMMA))); g=MinSIMD(pixscale,MulSIMD(pixscale,PowSIMD(intens.y,IGAMMA))); b=MinSIMD(pixscale,MulSIMD(pixscale,PowSIMD(intens.z,IGAMMA))); // now, convert to integer r=AndSIMD( AddSIMD( r, Four_MagicNumbers ), PIXMASK ); g=AndSIMD( AddSIMD( g, Four_MagicNumbers ), PIXMASK ); b=AndSIMD( AddSIMD( b, Four_MagicNumbers ), PIXMASK ); *(p1)=(SubInt(r, 0))|(SubInt(g, 0)<<8)|(SubInt(b, 0)<<16); *(p2)=(SubInt(r, 1))|(SubInt(g, 1)<<8)|(SubInt(b, 1)<<16); *(p3)=(SubInt(r, 2))|(SubInt(g, 2)<<8)|(SubInt(b, 2)<<16); *(p4)=(SubInt(r, 3))|(SubInt(g, 3)<<8)|(SubInt(b, 3)<<16); }
void LightDesc_t::ComputeLightAtPoints( const FourVectors &pos, const FourVectors &normal, FourVectors &color, bool DoHalfLambert ) const { FourVectors delta; Assert((m_Type==MATERIAL_LIGHT_POINT) || (m_Type==MATERIAL_LIGHT_SPOT) || (m_Type==MATERIAL_LIGHT_DIRECTIONAL)); switch (m_Type) { case MATERIAL_LIGHT_POINT: case MATERIAL_LIGHT_SPOT: delta.DuplicateVector(m_Position); delta-=pos; break; case MATERIAL_LIGHT_DIRECTIONAL: ComputeLightAtPointsForDirectional( pos, normal, color, DoHalfLambert ); return; default: return; } fltx4 dist2 = delta*delta; dist2=MaxSIMD( Four_Ones, dist2 ); fltx4 falloff; if( m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 ) { falloff = ReplicateX4(m_Attenuation0); } else falloff= Four_Epsilons; if( m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 ) { falloff=AddSIMD(falloff,MulSIMD(ReplicateX4(m_Attenuation1),SqrtEstSIMD(dist2))); } if( m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 ) { falloff=AddSIMD(falloff,MulSIMD(ReplicateX4(m_Attenuation2),dist2)); } falloff=ReciprocalEstSIMD(falloff); // Cull out light beyond this radius // now, zero out elements for which dist2 was > range^2. !!speed!! lights should store dist^2 in sse format if (m_Range != 0.f) { fltx4 RangeSquared=ReplicateX4(m_RangeSquared); // !!speed!! falloff=AndSIMD(falloff,CmpLtSIMD(dist2,RangeSquared)); } delta.VectorNormalizeFast(); fltx4 strength=delta*normal; if (DoHalfLambert) { strength=AddSIMD(MulSIMD(strength,Four_PointFives),Four_PointFives); } else strength=MaxSIMD(Four_Zeros,delta*normal); switch(m_Type) { case MATERIAL_LIGHT_POINT: // half-lambert break; case MATERIAL_LIGHT_SPOT: { fltx4 dot2=SubSIMD(Four_Zeros,delta*m_Direction); // dot position with spot light dir for cone falloff fltx4 cone_falloff_scale=MulSIMD(ReplicateX4(m_OneOverThetaDotMinusPhiDot), SubSIMD(dot2,ReplicateX4(m_PhiDot))); cone_falloff_scale=MinSIMD(cone_falloff_scale,Four_Ones); if ((m_Falloff!=0.0) && (m_Falloff!=1.0)) { // !!speed!! could compute integer exponent needed by powsimd and store in light cone_falloff_scale=PowSIMD(cone_falloff_scale,m_Falloff); } strength=MulSIMD(cone_falloff_scale,strength); // now, zero out lighting where dot2<phidot. This will mask out any invalid results // from pow function, etc fltx4 OutsideMask=CmpGtSIMD(dot2,ReplicateX4(m_PhiDot)); // outside light cone? strength=AndSIMD(OutsideMask,strength); } break; default: break; } strength=MulSIMD(strength,falloff); color.x=AddSIMD(color.x,MulSIMD(strength,ReplicateX4(m_Color.x))); color.y=AddSIMD(color.y,MulSIMD(strength,ReplicateX4(m_Color.y))); color.z=AddSIMD(color.z,MulSIMD(strength,ReplicateX4(m_Color.z))); }