162 lines
4.5 KiB
C++
162 lines
4.5 KiB
C++
/* -----------------------------------------------------------------------------
|
|
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 <Light *> &list, uint limit) const
|
|
{
|
|
list.Clear();
|
|
|
|
// On very large scenes filtering items by type can become very slow.
|
|
#if 0
|
|
nSharedList <nMLight *> lights;
|
|
if (!scene->GetItemListByType(lights))
|
|
return;
|
|
#else
|
|
List <MLight *> 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 <Light *> &list, uint limit) const
|
|
{
|
|
list.Clear();
|
|
|
|
#if 0
|
|
nSharedList <nMLight *> lights;
|
|
if (!scene->GetItemListByType(lights))
|
|
return;
|
|
#else
|
|
List <MLight *> lights;
|
|
scene->GetLightList().Clone(lights);
|
|
#endif
|
|
|
|
Array <Sort <float, MLight *>::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 <float, MLight *>::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);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|