#include "AdeptHeaders.hpp" #include "LightManager.hpp" #include "CollisionVolume.hpp" #include #include #include #include #include #include #include #include "CollisionGrid.hpp" #include "Tile.hpp" #include "Map.hpp" #include "Zone.hpp" #include #include #include #include #include #include #include #include "VideoRenderer.hpp" #include #include #include static DWORD Light_Count=0; extern void _stdcall End3DScene(); DECLARE_TIMER(static, Shadow_Casting); DECLARE_TIMER(static, Shadow_Start); DECLARE_TIMER(static, Shadow_Traversal); DECLARE_TIMER(static, Shadow_End); #define HUNT_LIGHT_CRASH #if 0 #define SHADOW_RENDER(string) RENDER("Shadow::" string) #else #define SHADOW_RENDER(string) #endif //------------------------------------------------------------------------------ // EnvironmentalLight::EnvironmentalLight(MidLevelRenderer::MLRLight *light): gosFX::Light(light) { Check_Pointer(this); Check_Object(light); } //------------------------------------------------------------------------------ // EnvironmentalLight::~EnvironmentalLight() { Check_Object(this); } //------------------------------------------------------------------------------ // AmbientLight::AmbientLight(MidLevelRenderer::MLRAmbientLight *light): EnvironmentalLight(light) { Check_Pointer(this); Check_Object(light); } //------------------------------------------------------------------------------ // InfiniteLight::InfiniteLight(MidLevelRenderer::MLRInfiniteLight *light): EnvironmentalLight(light) { Check_Pointer(this); Check_Object(light); } //------------------------------------------------------------------------------ // LookupLight::LookupLight(MidLevelRenderer::MLRLookUpLight *light): InfiniteLight(light) { Check_Pointer(this); Check_Object(light); } //------------------------------------------------------------------------------ // FiniteLight::FiniteLight(MidLevelRenderer::MLRInfiniteLightWithFalloff *light): gosFX::Light(light) { Check_Pointer(this); Check_Object(light); m_minRow = m_maxRow = m_minColumn = m_maxColumn = 255; Set_Statistic(Light_Count, Light_Count+1); if (light->GetLightMask()&MidLevelRenderer::MLRState::LightMapLightingMode) light->SetDynamicLight(); } //------------------------------------------------------------------------------ // FiniteLight::~FiniteLight() { Check_Object(this); Set_Statistic(Light_Count, Light_Count-1); if (CollisionGrid::Instance && m_minRow != 255) { Check_Object(CollisionGrid::Instance); for (BYTE z=m_minRow; z<=m_maxRow; ++z) { for (BYTE x=m_minColumn; x<=m_maxColumn; ++x) { Tile *tile = CollisionGrid::Instance->GetTile(z, x); Check_Object(tile); tile->m_lightsChanged = true; } } } } //------------------------------------------------------------------------------ // void FiniteLight::ChangeLight(gosFX::LightManager::Info *info) { Check_Object(this); Check_Pointer(info); // //----------------------------------------------------------------------- // Update the radius, then compute what the new tile limits of the lights // are //----------------------------------------------------------------------- // // BaseClass::ChangeLight(info); Check_Object(CollisionGrid::Instance); Scalar row_scale = 1.0f/CollisionGrid::Instance->m_rowCellSize; Scalar column_scale = 1.0f/CollisionGrid::Instance->m_columnCellSize; Scalar x = info->m_origin(3,0); Scalar z = info->m_origin(3,2); // //------------------------------- // Figure out the grid boundaries //------------------------------- // Scalar min_z = (z - info->m_outer - CollisionGrid::Instance->m_rowOffset) * row_scale; BYTE min_row = (min_z < 0.0f) ? (BYTE)0 : Truncate_Float_To_Byte(min_z); Scalar max_z = (z + info->m_outer - CollisionGrid::Instance->m_rowOffset) * row_scale; BYTE max_row = Truncate_Float_To_Byte(max_z); if (max_row >= CollisionGrid::Instance->m_rowCellCount) max_row = static_cast(CollisionGrid::Instance->m_rowCellCount - 1); Scalar min_x = (x - info->m_outer - CollisionGrid::Instance->m_columnOffset) * column_scale; BYTE min_col = (min_x < 0.0f) ? (BYTE)0 : Truncate_Float_To_Byte(min_x); Scalar max_x = (x + info->m_outer - CollisionGrid::Instance->m_columnOffset) * column_scale; BYTE max_col = Truncate_Float_To_Byte(max_x); if (max_col >= CollisionGrid::Instance->m_columnCellCount) max_col = static_cast(CollisionGrid::Instance->m_columnCellCount - 1); // //------------------------------------------------ // Update the tile boundaries if they have changed //------------------------------------------------ // if ( min_row != m_minRow || max_row != m_maxRow || min_col != m_minColumn || max_col != m_maxColumn || (info->m_intensityGetIntensity()m_columnCellCount ); Verify( m_minRow <= m_maxRow && m_maxRow < CollisionGrid::Instance->m_rowCellCount ); for (BYTE z=m_minRow; z<=m_maxRow; ++z) { for (BYTE x=m_minColumn; x<=m_maxColumn; ++x) { Tile *tile = CollisionGrid::Instance->GetTile(z, x); Check_Object(tile); tile->m_lights.RemovePlug(this); tile->m_lightsChanged = true; } } } // //------------------------ // Add it to the new zones //------------------------ // m_minRow = min_row; m_maxRow = max_row; m_minColumn = min_col; m_maxColumn = max_col; Verify( m_minColumn <= m_maxColumn && m_maxColumn < CollisionGrid::Instance->m_columnCellCount ); Verify( m_minRow <= m_maxRow && m_maxRow < CollisionGrid::Instance->m_rowCellCount ); if(info->m_intensity > Stuff::SMALL) { for (BYTE z=m_minRow; z<=m_maxRow; ++z) { for (BYTE x=m_minColumn; x<=m_maxColumn; ++x) { Tile *tile = CollisionGrid::Instance->GetTile(z, x); Check_Object(tile); tile->m_lights.Add(this); tile->m_lightsChanged = true; } } } } BaseClass::ChangeLight(info); MidLevelRenderer::MLRInfiniteLightWithFalloff *light = GetMLRLight(); Check_Object(light); light->SetFalloffDistance(info->m_inner, info->m_outer); } //------------------------------------------------------------------------------ // void FiniteLight::GetInfo(gosFX::LightManager::Info *info) { Check_Object(this); Check_Pointer(info); BaseClass::GetInfo(info); MidLevelRenderer::MLRInfiniteLightWithFalloff *light = GetMLRLight(); Check_Object(light); light->GetFalloffDistance( info->m_inner, info->m_outer ); } //------------------------------------------------------------------------------ // PointLight::PointLight(MidLevelRenderer::MLRPointLight *light): FiniteLight(light) { Check_Pointer(this); Check_Object(light); gosFX::LightManager::Info info; PointLight::GetInfo(&info); if (info.m_outer > 0.0f) PointLight::ChangeLight(&info); } //------------------------------------------------------------------------------ // SpotLight::SpotLight(MidLevelRenderer::MLRSpotLight *light): FiniteLight(light) { Check_Pointer(this); Check_Object(light); gosFX::LightManager::Info info; SpotLight::GetInfo(&info); if (info.m_outer > 0.0f) SpotLight::ChangeLight(&info); } //------------------------------------------------------------------------------ // void SpotLight::ChangeLight(gosFX::LightManager::Info *info) { Check_Object(this); Check_Pointer(info); BaseClass::ChangeLight(info); MidLevelRenderer::MLRSpotLight *light = GetMLRLight(); Check_Object(light); light->SetSpreadAngle(info->m_spread); } //------------------------------------------------------------------------------ // void SpotLight::GetInfo(gosFX::LightManager::Info *info) { Check_Object(this); Check_Pointer(info); BaseClass::GetInfo(info); MidLevelRenderer::MLRSpotLight *light = GetMLRLight(); Check_Object(light); light->GetSpreadAngle(&info->m_spread); } //------------------------------------------------------------------------------ // ProjectLight::ProjectLight(MidLevelRenderer::MLRProjectLight *light): FiniteLight(light) { Check_Pointer(this); Check_Object(light); gosFX::LightManager::Info info; ProjectLight::GetInfo(&info); if (info.m_outer > 0.0f) ProjectLight::ChangeLight(&info); } //------------------------------------------------------------------------------ // void ProjectLight::ChangeLight(gosFX::LightManager::Info *info) { Check_Object(this); Check_Pointer(info); BaseClass::ChangeLight(info); MidLevelRenderer::MLRProjectLight *light = GetMLRLight(); Check_Object(light); light->SetSpreadAngle(info->m_spread); } //------------------------------------------------------------------------------ // void ProjectLight::GetInfo(gosFX::LightManager::Info *info) { Check_Object(this); Check_Pointer(info); BaseClass::GetInfo(info); MidLevelRenderer::MLRProjectLight *light = GetMLRLight(); Check_Object(light); light->GetSpreadAngle(&info->m_spread); } //------------------------------------------------------------------------------ // ShadowLight::ShadowLight(MidLevelRenderer::MLRShadowLight *light): FiniteLight(light) { Check_Pointer(this); Check_Object(light); } //------------------------------------------------------------------------------ // void ShadowLight::ChangeLight(gosFX::LightManager::Info *info) { Check_Object(this); Check_Pointer(info); BaseClass::ChangeLight(info); // MidLevelRenderer::MLRShadowLight *light = GetMLRLight(); // Check_Object(light); } //------------------------------------------------------------------------------ // void ShadowLight::GetInfo(gosFX::LightManager::Info *info) { Check_Object(this); Check_Pointer(info); BaseClass::GetInfo(info); // MidLevelRenderer::MLRShadowLight *light = GetMLRLight(); // Check_Object(light); } //------------------------------------------------------------------------------ // CenterPointLight::CenterPointLight(MidLevelRenderer::MLRCenterPointLight *light): FiniteLight(light) { Check_Pointer(this); Check_Object(light); gosFX::LightManager::Info info; CenterPointLight::GetInfo(&info); if (info.m_outer > 0.0f) CenterPointLight::ChangeLight(&info); } //############################################################################ //############################ LightManager ################################ //############################################################################ TiledLightManager* &TiledLightManager::Instance=*Cast_Pointer(TiledLightManager**, &gosFX::LightManager::Instance); TiledLightManager::ShadowMode TiledLightManager::s_ShadowMode=e_ArticulatedShadows; static bool __stdcall CheckNoShadows() { return TiledLightManager::s_ShadowMode==TiledLightManager::e_NoShadows; } static void __stdcall EnableNoShadows() { TiledLightManager::s_ShadowMode = TiledLightManager::e_NoShadows; } static bool __stdcall CheckSimpleShadows() { return TiledLightManager::s_ShadowMode==TiledLightManager::e_Shadows; } static void __stdcall EnableSimpleShadows() { TiledLightManager::s_ShadowMode = TiledLightManager::e_Shadows; } static bool __stdcall CheckArticulatedShadows() { return TiledLightManager::s_ShadowMode==TiledLightManager::e_ArticulatedShadows; } static void __stdcall EnableArticulatedShadows() { TiledLightManager::s_ShadowMode = TiledLightManager::e_ArticulatedShadows; } //------------------------------------------------------------------------------ // void TiledLightManager::InitializeClass(NotationFile *startup_ini) { Verify(!Instance); gos_PushCurrentHeap(VideoRenderer::s_Heap); Instance = new TiledLightManager; gos_PopCurrentHeap(); #if !defined(NO_STATS) AddStatistic("Local Lights", "lights", gos_DWORD, &Light_Count, 0); #endif Initialize_Timer(Shadow_Casting, "Shadow Casting"); Initialize_Timer(Shadow_Start, " Shadow Texture Start"); Initialize_Timer(Shadow_Traversal, " Shadow Traversal"); Initialize_Timer(Shadow_End, " Shadow Texture End"); AddDebuggerMenuItem("Libraries\\Graphics Options\\No Shadows", CheckNoShadows, EnableNoShadows, 0 ); AddDebuggerMenuItem("Libraries\\Graphics Options\\Simple Shadows", CheckSimpleShadows, EnableSimpleShadows, 0 ); AddDebuggerMenuItem("Libraries\\Graphics Options\\Articulated Shadows", CheckArticulatedShadows, EnableArticulatedShadows, 0 ); if (startup_ini) { Check_Object(startup_ini); Page *page = startup_ini->FindPage("Graphics Options"); if (page) { Check_Object(page); int mode; if (page->GetEntry("ShadowMode", &mode)) s_ShadowMode = static_cast(mode); } } } //------------------------------------------------------------------------------ // void TiledLightManager::TerminateClass(NotationFile *startup_ini) { // MSL 5.02 Prevent Option Overwrite // Prevents Software from Overwriting Options.ini Settings // if (startup_ini) // { // Check_Object(startup_ini); // Page *page = startup_ini->SetPage("Graphics Options"); // Check_Object(page); // int mode = s_ShadowMode; // page->SetEntry("ShadowMode", mode); // } Check_Object(Instance); delete Instance; Instance = NULL; } //------------------------------------------------------------------------------ // TiledLightManager::TiledLightManager(): m_shadows(NULL) { } //------------------------------------------------------------------------------ // TiledLightManager::~TiledLightManager() { } //------------------------------------------------------------------------------ // gosFX::Light* TiledLightManager::MakeAmbientLight() { Check_Object(this); gos_PushCurrentHeap(MidLevelRenderer::LightsHeap); MidLevelRenderer::MLRAmbientLight *mlr_light = new MidLevelRenderer::MLRAmbientLight; Check_Object(mlr_light); gos_PopCurrentHeap(); return new AmbientLight(mlr_light); } //------------------------------------------------------------------------------ // gosFX::Light* TiledLightManager::MakeInfiniteLight() { Check_Object(this); gos_PushCurrentHeap(MidLevelRenderer::LightsHeap); MidLevelRenderer::MLRInfiniteLight *mlr_light = new MidLevelRenderer::MLRInfiniteLight; Check_Object(mlr_light); gos_PopCurrentHeap(); return new InfiniteLight(mlr_light); } //------------------------------------------------------------------------------ // gosFX::Light* TiledLightManager::MakeLookupLight() { Check_Object(this); gos_PushCurrentHeap(MidLevelRenderer::LightsHeap); MidLevelRenderer::MLRLookUpLight *mlr_light = new MidLevelRenderer::MLRLookUpLight; Check_Object(mlr_light); gos_PopCurrentHeap(); return new InfiniteLight(mlr_light); } //------------------------------------------------------------------------------ // gosFX::Light* TiledLightManager::MakePointLight( const char* light_map, bool light_vertex ) { Check_Object(this); gos_PushCurrentHeap(MidLevelRenderer::LightsHeap); MidLevelRenderer::MLRPointLight *mlr_light = new MidLevelRenderer::MLRPointLight; Check_Object(mlr_light); if (light_map) { MString name = light_map; Check_Object(MidLevelRenderer::MLRTexturePool::Instance); MidLevelRenderer::MLRTexture *texture = (*MidLevelRenderer::MLRTexturePool::Instance)(name, 0); if (!texture) texture = MidLevelRenderer::MLRTexturePool::Instance->Add(name, 0); Check_Object(texture); MidLevelRenderer::MLRLightMap *map = new MidLevelRenderer::MLRLightMap(texture); Check_Object(map); mlr_light->SetLightMap(map); if (!light_vertex) { int mask = mlr_light->GetLightMask(); mask &= ~MidLevelRenderer::MLRState::VertexLightingMode; mlr_light->SetLightMask(mask); } } gos_PopCurrentHeap(); return new PointLight(mlr_light); } //------------------------------------------------------------------------------ // gosFX::Light* TiledLightManager::MakeSpotLight( const char* light_map, bool light_vertex ) { Check_Object(this); gos_PushCurrentHeap(MidLevelRenderer::LightsHeap); MidLevelRenderer::MLRSpotLight *mlr_light = new MidLevelRenderer::MLRSpotLight; Check_Object(mlr_light); gos_PopCurrentHeap(); if (light_map) { MString name = light_map; Check_Object(MidLevelRenderer::MLRTexturePool::Instance); MidLevelRenderer::MLRTexture *texture = (*MidLevelRenderer::MLRTexturePool::Instance)(name, 0); if (!texture) texture = MidLevelRenderer::MLRTexturePool::Instance->Add(name, 0); Check_Object(texture); MidLevelRenderer::MLRLightMap *map = new MidLevelRenderer::MLRLightMap(texture); Check_Object(map); mlr_light->SetLightMap(map); if (!light_vertex) { int mask = mlr_light->GetLightMask(); mask &= ~MidLevelRenderer::MLRState::VertexLightingMode; mlr_light->SetLightMask(mask); } } return new SpotLight(mlr_light); } //------------------------------------------------------------------------------ // gosFX::Light* TiledLightManager::MakeProjectLight( const char* light_map, bool light_vertex ) { Check_Object(this); gos_PushCurrentHeap(MidLevelRenderer::LightsHeap); MidLevelRenderer::MLRProjectLight *mlr_light = new MidLevelRenderer::MLRProjectLight; Check_Object(mlr_light); gos_PopCurrentHeap(); if (light_map) { MString name = light_map; Check_Object(MidLevelRenderer::MLRTexturePool::Instance); MidLevelRenderer::MLRTexture *texture = (*MidLevelRenderer::MLRTexturePool::Instance)(name, 0); if (!texture) texture = MidLevelRenderer::MLRTexturePool::Instance->Add(name, 0); Check_Object(texture); MidLevelRenderer::MLRLightMap *map = new MidLevelRenderer::MLRLightMap(texture); Check_Object(map); mlr_light->SetLightMap(map); if (!light_vertex) { int mask = mlr_light->GetLightMask(); mask &= ~MidLevelRenderer::MLRState::VertexLightingMode; mlr_light->SetLightMask(mask); } } return new ProjectLight(mlr_light); } //------------------------------------------------------------------------------ // gosFX::Light* TiledLightManager::MakeShadowLight( const char* light_map, bool light_vertex ) { Check_Object(this); gos_PushCurrentHeap(MidLevelRenderer::LightsHeap); MidLevelRenderer::MLRShadowLight *mlr_light = new MidLevelRenderer::MLRShadowLight; Check_Object(mlr_light); gos_PopCurrentHeap(); if (light_map) { MString name = light_map; Check_Object(MidLevelRenderer::MLRTexturePool::Instance); MidLevelRenderer::MLRTexture *texture = (*MidLevelRenderer::MLRTexturePool::Instance)(name, 0); if (!texture) texture = MidLevelRenderer::MLRTexturePool::Instance->Add(name, 0); Check_Object(texture); MidLevelRenderer::MLRLightMap *map = new MidLevelRenderer::MLRLightMap(texture); Check_Object(map); mlr_light->SetLightMap(map); if (!light_vertex) { int mask = mlr_light->GetLightMask(); mask &= ~MidLevelRenderer::MLRState::VertexLightingMode; mlr_light->SetLightMask(mask); } } return new ShadowLight(mlr_light); } //------------------------------------------------------------------------------ // gosFX::Light* TiledLightManager::MakeLight(MidLevelRenderer::MLRLight *light) { Check_Object(this); if (light->IsDerivedFrom(MidLevelRenderer::MLRAmbientLight::DefaultData)) return new AmbientLight(Cast_Object(MidLevelRenderer::MLRAmbientLight*, light)); if (light->IsDerivedFrom(MidLevelRenderer::MLRLookUpLight::DefaultData)) return new LookupLight(Cast_Object(MidLevelRenderer::MLRLookUpLight*, light)); if (light->IsDerivedFrom(MidLevelRenderer::MLRInfiniteLight::DefaultData)) return new InfiniteLight(Cast_Object(MidLevelRenderer::MLRInfiniteLight*, light)); if (light->IsDerivedFrom(MidLevelRenderer::MLRSpotLight::DefaultData)) return new SpotLight(Cast_Object(MidLevelRenderer::MLRSpotLight*, light)); if (light->IsDerivedFrom(MidLevelRenderer::MLRPointLight::DefaultData)) return new PointLight(Cast_Object(MidLevelRenderer::MLRPointLight*, light)); if (light->IsDerivedFrom(MidLevelRenderer::MLRProjectLight::DefaultData)) return new ProjectLight(Cast_Object(MidLevelRenderer::MLRProjectLight*, light)); if (light->IsDerivedFrom(MidLevelRenderer::MLRShadowLight::DefaultData)) { ShadowLight *shadow = new ShadowLight(Cast_Object(MidLevelRenderer::MLRShadowLight*, light)); Check_Object(shadow); m_shadows.Add(shadow); return shadow; } STOP(("Non-supported light")); return NULL; } //------------------------------------------------------------------------------ // void TiledLightManager::CastShadows(ElementRenderer::CameraElement *camera) { Check_Object(this); // //------------------------------------------------------------------------ // Go through the list of shadows, checking each light for its LOD setting //------------------------------------------------------------------------ // if (s_ShadowMode == e_NoShadows) return; SHADOW_RENDER(""); Start_Timer(ElementRenderer::Total_Video); Start_Timer(Shadow_Casting); const LinearMatrix4D &camera_to_world = camera->GetLocalToWorld(); ChainIteratorOf shadows(&m_shadows); ShadowLight *shadow; while ((shadow = shadows.ReadAndNext()) != NULL) { Check_Object(shadow); // //--------------------------------------------------------------------- // Get the shadow information and set the shadow to the default mode of // blob //--------------------------------------------------------------------- // MidLevelRenderer::MLRShadowLight *shadow_light = shadow->GetMLRLight(); Check_Object(shadow_light); Info info; shadow->GetInfo(&info); shadow_light->SeeDetailShadow(false); Scalar blob_distance = shadow_light->GetBlobDistance(); // //-------------------------------------------------------------------- // Get the light information and compute the vector between the center // of the shadow and the eye (normalized to the x-z plane). If we are // too far away, or if shadows are simple, don't articulate //-------------------------------------------------------------------- // Vector3D dist( camera_to_world(3,0) - info.m_origin(3,0), 0.0f, camera_to_world(3,2) - info.m_origin(3,2) ); if (dist.GetLengthSquared() >= blob_distance*blob_distance || s_ShadowMode==e_Shadows) continue; // //--------------------------------------------------------- // Make sure that the shadow is within the viewing frustrum //--------------------------------------------------------- // Point3D center(info.m_origin); const Plane* plane = &camera->GetWorldCullingPlane(0); for (int i=0; iGetDistanceTo(center); if (distance >= info.m_inner) break; } if (i= -SMALL) continue; // //------------------------------------------------------------------- // The shadow will be in the frustrum and close enough, so now set up // the renderer and the rasterizer to start drawing the object //------------------------------------------------------------------- // MidLevelRenderer::MLRState dState; camera->GetClipper()->StartDraw( Stuff::LinearMatrix4D::Identity, Stuff::Matrix4D::Identity, Stuff::RGBAColor::White, &Stuff::RGBAColor::White, dState, NULL ); const MidLevelRenderer::MLRTexture *shadow_texture = shadow_light->GetShadowTexture(); Check_Object(shadow_texture); { SHADOW_RENDER("Start Render"); Start_Timer(Shadow_Start); gos_StartRenderToTexture( shadow_texture->GetImage()->GetHandle() ); Stop_Timer(Shadow_Start); } // //--------------------------------------------------------------------- // Compute where the sun would strike a x-z plane containing the origin // of the vehicle if the ray runs thru the center of the vehicle's // collision volume //--------------------------------------------------------------------- // SHADOW_RENDER("Traversal"); { Start_Timer(Shadow_Traversal); Entity *vehicle = Cast_Object(Entity*, shadow->m_shadowCaster->GetClientData()); CollisionVolume *cv = vehicle->GetSolidVolume(); #if defined(HUNT_LIGHT_CRASH) && defined(LAB_ONLY) if (cv == NULL) { if (vehicle->instanceName) { const char *name; name = vehicle->GetModelName (); STOP(("VEHICLE HAS NO CV : %s : %s", (char *)vehicle->instanceName, name)); } else { const char *name; name = vehicle->GetModelName (); STOP(("VEHICLE HAS NO CV : noname : %s", name)); } } #endif Check_Object(cv); LinearMatrix4D world_bounds; world_bounds.Multiply(cv->m_localSpaceBounds.localToParent, vehicle->GetLocalToWorld()); Stuff::Point3D shadow_translation(world_bounds); Stuff::Point3D vehicle_translation(shadow->m_shadowCaster->GetLocalToWorld()); Stuff::Scalar height = shadow_translation.y - vehicle_translation.y; shadow_translation.AddScaled(shadow_translation, sun_light, -height/sun_light.y); // //------------------------------------------------------------------- // The matrix will face the way the light did, but it will ignore any // pitch by aligning the local Y axis to the world Y axis //------------------------------------------------------------------- // Stuff::LinearMatrix4D shadow_plane_matrix(info.m_origin); shadow_plane_matrix.BuildTranslation(shadow_translation); shadow_plane_matrix.AlignLocalAxisToWorldVector(Stuff::Vector3D::Up, Y_Axis, X_Axis, Z_Axis); // //------------------------------------------------------ // Now actually traverse the targeted object and draw it //------------------------------------------------------ // shadow->m_shadowCaster->CastShadow( shadow_plane_matrix, sun_light, info.m_outer ); Stop_Timer(Shadow_Traversal); } // //-------------- // Now rasterize //-------------- // { SHADOW_RENDER("End Render"); Start_Timer(Shadow_End); gos_EndRenderToTexture(true); End3DScene(); Stop_Timer(Shadow_End); } // //----------------------------------------------------------------- // Set up some parameters for the shadow - the falloff distance bit // is flaky //----------------------------------------------------------------- // shadow_light->SeeDetailShadow(true); } Stop_Timer(Shadow_Casting); Stop_Timer(ElementRenderer::Total_Video); }