/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "scene3d/scene_renderer_environment_interface.h" #include "scene3d/mlight.h" #include "scene3d/scene.h" #include "physic/physic_world.h" #include "core/renderer.h" #include "sort/sort.h" using namespace GS; using namespace GS::Core; using namespace GS::S3D; //------------------------------------------------------------------------------ float IEnvironment::GetClock() const { return scene->GetClock()->Getf(); } float IEnvironment::GetTimeOfDay() const { return scene->time_of_day; } Render::Shader *IEnvironment::GetSkyboxShader() const { return scene->render_data ? scene->render_data->skybox_shader.c_ptr() : NULL; } bool IEnvironment::GetSkyboxLayers(Render::sTexture layers[2]) const { if (scene->render_data.IsValid()) for (uint n = 0; n < 2; ++n) layers[n] = scene->render_data->skybox_layer[n]; return layers[0].IsValid() && layers[1].IsValid(); } void IEnvironment::GetEnvironmentProbe(Render::sTexture &radiance, Render::sTexture &irradiance) const { if (scene->render_data.IsValid()) { radiance = scene->render_data->radiance_probe; irradiance = scene->render_data->irradiance_probe; } } bool IEnvironment::IsFogEnabled() const { return scene->fog_far > 0.f; } bool IEnvironment::GetFogConfiguration(Color &color, float &fog_near, float &fog_far) const { if (scene->fog_far < 0.f) return false; color = scene->fog_color; fog_near = scene->fog_near; fog_far = scene->fog_far; return true; } Color IEnvironment::GetClearColor() const { return scene->background_color; } Color IEnvironment::GetAmbientColor() const { return scene->ambient_color * scene->ambient_intensity; } static float CompareLightPriority(const MLight *a, const MLight *b) { return a->GetPriority() - b->GetPriority(); } void IEnvironment::GetLightsInFrustum(const Vector4 &world_pos, const Frustum &frustum, List &list, uint limit) const { list.Clear(); // On very large scenes filtering items by type can become very slow. #if 0 nSharedList lights; if (!scene->GetItemListByType(lights)) return; #else List lights; scene->GetLightList().Clone(lights); #endif lights.Sort(CompareLightPriority); ListForeachPtr(MLight *, l, lights) { if (!l->isActive()) continue; // Check light range and clip distance. if (l->range) { if (Vector4::Dist(world_pos, l->GetMatrix().GetRow(3)) >= (l->clip_distance + l->range)) continue; // Check frustum intersection. switch (l->model) { case Light::Model_Point: if (frustum.ClassifySphere(l->GetMatrix().GetRow(3), l->range) == Frustum::Outside) continue; break; case Light::Model_Spot: if (frustum.ClassifyFrustrum(l->frustum) == Frustum::Outside) continue; break; default: break; } } list.Add(l); if (list.GetCount() == limit) break; } } void IEnvironment::GetClosestLights(const Vector4 &world_pos, List &list, uint limit) const { list.Clear(); #if 0 nSharedList lights; if (!scene->GetItemListByType(lights)) return; #else List lights; scene->GetLightList().Clone(lights); #endif Array ::Entry> array(lights.GetCount()); if (!array) __ERRRAW__(__LOG_E__ << "Failed to allocated sort structure.\n") int c = 0; ListForeachPtr(MLight *, l, lights) if (l->isActive()) { array[c].o = l; array[c].v = Vector4::Dist2(world_pos, l->GetMatrix().GetRow(3)) * (1.f - l->GetPriority()); ++c; } Sort ::QuickSort(c, array); for (int n = 0; n < c; n++) { list.Add(array[n].o); if (list.GetCount() == limit) break; } } Camera *IEnvironment::GetCurrentCamera() const { return scene->current_camera; } void IEnvironment::OnRenderUser(Renderer *renderer) const { scene->scene_event->OnRenderUser(scene); // Debug physics. if (scene->flags.IsSet(Scene::FlagDebugPhysics)) if (PhysicWorld *world = scene->physic_world) { if (!world->HasDebugger()) world->CreateDebugger(renderer); renderer->SetWorldMatrix(Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix()); renderer->ApplyCamera(); world->DrawDebug(*renderer, scene->current_camera, NULL/*profiler_font[0]*/, true); world->DrawDebug(*renderer, scene->current_camera, NULL/*profiler_font[0]*/, false); } } //------------------------------------------------------------------------------