commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
227
include/engine/core/light.cpp
Normal file
227
include/engine/core/light.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "core/light.h"
|
||||
#include "core/resource_factories.h"
|
||||
#include "core/render_resource_factory.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Light::ComputeProjectionMatrix(Matrix4 &m) const
|
||||
{
|
||||
switch (model)
|
||||
{
|
||||
case Model_Spot:
|
||||
{
|
||||
const float q = volume_range / (volume_range - z_near),
|
||||
fov = (cone_angle + edge_angle),
|
||||
zoom_factor = float(Math::Cos(fov) / Math::Sin(fov));
|
||||
|
||||
// Default aspect ration: PC(1:1).
|
||||
m.Set
|
||||
(
|
||||
zoom_factor, 0, 0, 0,
|
||||
0, zoom_factor, 0, 0,
|
||||
0, 0, q, 1,
|
||||
0, 0, -q * z_near, 0
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
m = Matrix4::IdentityMatrix();
|
||||
break;
|
||||
}
|
||||
}
|
||||
void Light::ComputeFrustrum(Frustum &f, float zn, float zf) const
|
||||
{
|
||||
if (model == Model_Spot)
|
||||
f.SetPerspective((cone_angle + edge_angle) * 2, zn != -1 ? zn : z_near, zf != -1 ? zf : volume_range, &GetMatrix(), 1, 1);
|
||||
}
|
||||
void Light::ComputeMatrix()
|
||||
{
|
||||
bool update_world = item_flags.IsSet(ItemFlagWorldMatrixDirty);
|
||||
|
||||
Item::ComputeMatrix();
|
||||
|
||||
// Remove scale from world matrix.
|
||||
if (update_world)
|
||||
{
|
||||
Vector4 u = matrix.GetRow(0).Normalized();
|
||||
matrix.m[0][0] = u.x; matrix.m[1][0] = u.y; matrix.m[2][0] = u.z;
|
||||
Vector4 v = matrix.GetRow(1).Normalized();
|
||||
matrix.m[0][1] = v.x; matrix.m[1][1] = v.y; matrix.m[2][1] = v.z;
|
||||
Vector4 w = matrix.GetRow(2).Normalized();
|
||||
matrix.m[0][2] = w.x; matrix.m[1][2] = w.y; matrix.m[2][2] = w.z;
|
||||
}
|
||||
ComputeFrustrum(frustum);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Light::SampleColor(const Vector4 &location, const Vector4 &normal, Color &diff, Color &spec, Vector4 *view, float gloss)
|
||||
{
|
||||
float idiff, ispec;
|
||||
|
||||
if (!SampleEnergy(location, normal, &idiff, &ispec, view, gloss, true, false))
|
||||
{
|
||||
diff.Set();
|
||||
spec.Set();
|
||||
return false;
|
||||
}
|
||||
|
||||
diff = diffuse_color * diffuse_intensity * idiff;
|
||||
spec = specular_color * specular_intensity * ispec;
|
||||
return true;
|
||||
}
|
||||
bool Light::SampleEnergy(const Vector4 &loc, const Vector4 &normal, float *diff, float *spec, Vector4 *view, float gloss, bool halfway, bool cooktorrance)
|
||||
{
|
||||
if (!diff && !spec)
|
||||
return false;
|
||||
|
||||
Vector4 dt;
|
||||
float a = 1;
|
||||
|
||||
switch (model)
|
||||
{
|
||||
case Model_Linear:
|
||||
dt = GetMatrix().GetRow(2).Reversed().Normalized();
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
dt = GetMatrix().GetRow(3) - loc;
|
||||
float dt_length = dt.Len();
|
||||
dt /= dt_length;
|
||||
|
||||
// Compute light attenuation.
|
||||
if (range)
|
||||
{
|
||||
float distance = dt_length / range;
|
||||
|
||||
switch (falloff)
|
||||
{
|
||||
/*
|
||||
case Falloff_InvDist:
|
||||
if (distance)
|
||||
a = 1 / distance;
|
||||
break;
|
||||
|
||||
case Falloff_InvDist2:
|
||||
if (distance)
|
||||
a = 1 / (distance * distance);
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
case Falloff_Linear:
|
||||
a = 1 - distance;
|
||||
break;
|
||||
}
|
||||
if (a <= 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (model == Model_Spot)
|
||||
{
|
||||
float c = Math::ACos(dt.Reversed().Dot(GetMatrix().GetRow(2).Normalized()));
|
||||
if ((c < 0) || (c > (cone_angle + edge_angle)))
|
||||
return false;
|
||||
if (c > cone_angle)
|
||||
a *= 1 - (c - cone_angle) / edge_angle;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Sample diffuse.
|
||||
float e = normal.Dot(dt);
|
||||
if (e < 0)
|
||||
return false;
|
||||
|
||||
if (diff)
|
||||
*diff = e * a * diffuse_intensity;
|
||||
|
||||
/*
|
||||
Sample specular.
|
||||
Use the halfway vector method if you'd like to avoid a vector reflection.
|
||||
*/
|
||||
if (spec)
|
||||
{
|
||||
*spec = 0;
|
||||
|
||||
if (view)
|
||||
{
|
||||
Vector4 local_view = view->Normalized();
|
||||
float e = 0;
|
||||
|
||||
if (cooktorrance)
|
||||
__LOG_W__ << "Cook-Torrance specular model not implemented.\n";
|
||||
|
||||
else
|
||||
{
|
||||
if (halfway)
|
||||
e = (dt - local_view).Normalized().Dot(normal);
|
||||
else e = local_view.Reflected(normal).Dot(dt);
|
||||
|
||||
e = (e > 0) ? Math::Pow(e, gloss * 96.f) : 0;
|
||||
}
|
||||
*spec = e * a * specular_intensity;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Light::RenderSetup(ResourceFactories *f)
|
||||
{
|
||||
render_data = new RenderData;
|
||||
if (f && f->render)
|
||||
if (!projection_texture.IsEmpty())
|
||||
render_data->projection_texture = f->render->LoadTexture(projection_texture);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Light::SetDefaults()
|
||||
{
|
||||
model = Light::Model_Point;
|
||||
shadow = Light::Shadow_None;
|
||||
|
||||
range = Units::Mtr(0.f);
|
||||
volume_range = Units::Mtr(500.f);
|
||||
clip_distance = Units::Mtr(300.f);
|
||||
cone_angle = Units::Deg(30.f);
|
||||
edge_angle = Units::Deg(30.f);
|
||||
|
||||
shadow_cast_all = false;
|
||||
shadow_bias = 0.01f;
|
||||
shadow_distribution = 0.9f;
|
||||
shadow_range = Units::Mtr(100.f);
|
||||
shadow_color.Set(0, 0, 0);
|
||||
|
||||
volumetric = false;
|
||||
volumetric_sample_step = 0.5f;
|
||||
volumetric_range = 8.0f;
|
||||
volumetric_thickness = 1.0f;
|
||||
|
||||
z_near = Units::Cm(2.f);
|
||||
falloff = Falloff_Linear;
|
||||
|
||||
diffuse_color = Color::White;
|
||||
diffuse_intensity = 1;
|
||||
specular_color = Color::White;
|
||||
specular_intensity = 0;
|
||||
}
|
||||
Light::Light()
|
||||
{
|
||||
SetDefaults();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user