616 lines
18 KiB
C++
Executable File
616 lines
18 KiB
C++
Executable File
//-----------------------------------------------
|
|
// Synapse Gaming - Lighting System
|
|
// Copyright © Synapse Gaming 2003
|
|
// Written by John Kabus
|
|
//-----------------------------------------------
|
|
#include "dgl/dgl.h"
|
|
#include "lightingSystem/sgLighting.h"
|
|
#include "lightingSystem/sgLightingModel.h"
|
|
#include "lightingSystem/sgLightManager.h"
|
|
#include "platform/profiler.h"
|
|
|
|
//#define SG_TEST_LIGHTING_TEXTURE
|
|
|
|
#define SG_LIGHTING_MIN_CUTOFF 0.00392f
|
|
#define SG_DYNAMIC_LIGHTING_TEXTURE_SIZE 16
|
|
#define SG_DYNAMIC_LIGHTING_TEXTURE_HALFSIZE F32(SG_DYNAMIC_LIGHTING_TEXTURE_SIZE / 2)
|
|
|
|
Vector<sgLightingModel *> sgLightingModelManager::sgLightingModels;
|
|
sgLightingModelStock sgLightingModelManager::sgDefaultModel;
|
|
sgLightingModelAdvanced sgLightingModelManager::sgAdvancedModel;
|
|
sgLightingModelInverseSquare sgLightingModelManager::sgInverseSquare;
|
|
sgLightingModelInverseSquareFastFalloff sgLightingModelManager::sgInverseSquareFastFalloff;
|
|
sgLightingModelNearLinear sgLightingModelManager::sgNearLinear;
|
|
sgLightingModelNearLinearFastFalloff sgLightingModelManager::sgNearLinearFastFalloff;
|
|
|
|
sgLightingModel *sgLightingModelManager::sgSunlightModel = &sgLightingModelManager::sgAdvancedModel;
|
|
|
|
|
|
#ifdef SG_TEST_LIGHTING_TEXTURE
|
|
GFXTexHandle sgTestLightingTexture;
|
|
#endif
|
|
|
|
|
|
ConsoleFunction(sgLightingModelCount, S32, 1, 1, "Get the number of Lighting Pack Lighting Models.")
|
|
{
|
|
return sgLightingModelManager::sgGetLightingModelCount();
|
|
}
|
|
|
|
ConsoleFunction(sgLightingModelName, const char *, 2, 2, "Get the name of the Lighting Pack Lighting Model.")
|
|
{
|
|
U32 index;
|
|
index = dAtoi(argv[1]);
|
|
return sgLightingModelManager::sgGetLightingModelName(index);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
//-----------------------------------------------
|
|
|
|
sgLightingModel::sgLightingModel()
|
|
{
|
|
sgStateSet = false;
|
|
sgStateInitLM = false;
|
|
sgLight = NULL;
|
|
sgLightingModelName[0] = 0;
|
|
sgLightingModelManager::sgRegisterLightingModel(this);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
//-----------------------------------------------
|
|
// only for TSE's consistent lighting models...
|
|
// TGE's vertex lighting requires the base
|
|
// class method sgLightingModelGLBase::sgScoreLight...
|
|
/*
|
|
F32 sgLightingModelAdvanced::sgScoreLight(LightInfo *light, const SphereF &sphere)
|
|
{
|
|
sgLightingModel::sgScoreLight(light, sphere);
|
|
|
|
F32 radsq = (light->mRadius * light->mRadius);
|
|
if(radsq <= 0.0f)
|
|
return 0.0f;
|
|
VectorF dist = light->mPos - sphere.center;
|
|
F32 distsq = dist.lenSquared();
|
|
return getMax((1 - (distsq / radsq)), 0.0f);
|
|
}
|
|
*/
|
|
bool sgLightingModelAdvanced::sgCanIlluminate(const Box3F &box)
|
|
{
|
|
AssertFatal((sgStateSet == true), "sgLightingModel: State not properly set.");
|
|
|
|
// can we skip the hard stuff?
|
|
if((sgLight->mType == LightInfo::Vector) || (sgLight->mType == LightInfo::Ambient))
|
|
return true;
|
|
|
|
// get the min dist...
|
|
Point3F pos = box.getClosestPoint(sgLight->mPos);
|
|
Point3F nor = sgLight->mPos - pos;
|
|
F32 distsq = mDot(nor, nor);
|
|
|
|
bool res = (distsq < (sgLight->mRadius * sgLight->mRadius));
|
|
return res;
|
|
}
|
|
|
|
void sgLightingModelAdvanced::sgSetState(LightInfo *light)
|
|
{
|
|
sgLightingModelGLBase::sgSetState(light);
|
|
|
|
if(sgLight->mRadius > 0.0f)
|
|
sgLinearAttenuation = (6.0f / sgLight->mRadius);
|
|
else
|
|
sgLinearAttenuation = 0.0f;
|
|
}
|
|
|
|
void sgLightingModelAdvanced::sgInitStateLM()
|
|
{
|
|
sgLightingModelGLBase::sgInitStateLM();
|
|
|
|
maxlightdistancesquared = sgLight->mRadius * sgLight->mRadius;
|
|
}
|
|
|
|
void sgLightingModelAdvanced::sgLightingLM(const Point3F &point, VectorF normal, ColorF &diffuse, ColorF &ambient, Point3F &lightingnormal)
|
|
{
|
|
// do not call sgLightingModelGLBase::sgLightingLM!!!
|
|
// we're overriding the method!!!
|
|
sgLightingModel::sgLightingLM(point, normal, diffuse, ambient, lightingnormal);
|
|
|
|
Point3F lightvector;
|
|
F32 distsquared;
|
|
F32 spotlightingangle;
|
|
|
|
// do this in lightmap...
|
|
//diffuse = ColorF(0.0, 0.0, 0.0);
|
|
//ambient = ColorF(0.0, 0.0, 0.0);
|
|
//lightingnormal = Point3F(0.0, 0.0, 0.0);
|
|
|
|
if(sgLight->mType != LightInfo::Vector)
|
|
{
|
|
// get the distance squared from the light to the
|
|
// light map texel world space coord.
|
|
lightvector = sgLight->mPos - point;
|
|
distsquared = lightvector.lenSquared();
|
|
|
|
if(distsquared >= maxlightdistancesquared)
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// directional lighting is always close enough
|
|
// just setup the needed variables...
|
|
lightvector = sgLight->mDirection * -1.0f;
|
|
}
|
|
|
|
// step two: find the spotlight amount...
|
|
|
|
// vector lights are already normallized...
|
|
if(sgLight->mType != LightInfo::Vector)
|
|
lightvector.normalize();
|
|
|
|
lightingnormal = lightvector;
|
|
|
|
// is it a spotlight? is it pointing this way?
|
|
if(sgLight->mType == LightInfo::SGStaticSpot)
|
|
{
|
|
spotlightingangle = mDot(lightvector, sgLight->mDirection);
|
|
if(spotlightingangle < spotanglecos)
|
|
return;
|
|
}
|
|
else
|
|
spotlightingangle = 1.0f;
|
|
|
|
// get the lighting angle amount...
|
|
// values coming from terrain are not normalized...
|
|
normal.normalize();
|
|
F32 angleamount = mDot(lightvector, normal);
|
|
F32 lightamount = 1.0f;
|
|
if(sgLight->sgUseNormals)
|
|
lightamount *= angleamount;
|
|
|
|
F32 lightfalloff = 1.0f;
|
|
lightamount = getMax(getMin(lightamount, 1.0f), 0.0f);
|
|
|
|
if(sgLight->mType != LightInfo::Vector)
|
|
{
|
|
// apply one of the point light lighting models...
|
|
lightfalloff = getMax((1 - (distsquared / maxlightdistancesquared)), 0.0f);
|
|
|
|
if(sgLight->mType == LightInfo::SGStaticSpot)
|
|
{
|
|
// apply the spotlight lighting model...
|
|
spotlightingangle = mClampF(((spotlightingangle - spotamountouter) / spotamountinner), 0.0f, 1.0f);
|
|
|
|
if(sgLight->sgSmoothSpotLight)
|
|
spotlightingangle *= getMin((spotlightingangle * 1.2f), 1.0f);
|
|
|
|
lightfalloff *= spotlightingangle;
|
|
}
|
|
|
|
lightamount *= lightfalloff;
|
|
}
|
|
|
|
lightamount *= (1.0f - sgLight->sgLocalAmbientAmount);
|
|
lightamount = getMax(getMin(lightamount, 1.0f), 0.0f);
|
|
diffuse = sgLight->mColor * lightamount;
|
|
|
|
if(sgLight->sgDoubleSidedAmbient || (angleamount > 0.0f))
|
|
{
|
|
lightfalloff *= sgLight->sgLocalAmbientAmount;
|
|
lightfalloff = getMax(getMin(lightfalloff, 1.0f), 0.0f);
|
|
ambient = sgLight->mColor * lightfalloff;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
//-----------------------------------------------
|
|
|
|
F32 sgLightingModelGLBase::sgScoreLight(LightInfo *light, const SphereF &sphere)
|
|
{
|
|
sgLightingModel::sgScoreLight(light, sphere);
|
|
|
|
if((sgLight->mType == LightInfo::Vector) || (sgLight->mType == LightInfo::Ambient))
|
|
return 0.5f;
|
|
|
|
VectorF vect = light->mPos - sphere.center;
|
|
F32 distsq = vect.lenSquared();
|
|
F32 dist = 0.0f;
|
|
|
|
if(sgLinearAttenuation > 0.0f)
|
|
{
|
|
dist = mSqrt(distsq);
|
|
}
|
|
|
|
F32 amount = (sgConstantAttenuation + (sgLinearAttenuation * dist) + (sgQuadraticAttenuation * distsq));
|
|
amount = getMax(amount, 0.000001f);
|
|
if(amount != 0.0f)
|
|
amount = 1.0f / amount;
|
|
amount = getMax(amount, 0.0f);
|
|
return amount;
|
|
}
|
|
|
|
bool sgLightingModelGLBase::sgCanIlluminate(const Box3F &box)
|
|
{
|
|
AssertFatal((sgStateSet == true), "sgLightingModel: State not properly set.");
|
|
|
|
// can we skip the hard stuff?
|
|
if((sgLight->mType == LightInfo::Vector) || (sgLight->mType == LightInfo::Ambient))
|
|
return true;
|
|
|
|
// get the min dist...
|
|
Point3F pos = box.getClosestPoint(sgLight->mPos);
|
|
Point3F nor = sgLight->mPos - pos;
|
|
F32 distsq = mDot(nor, nor);
|
|
F32 intensity = 0.0f;
|
|
|
|
if(distsq > 0.0f)
|
|
{
|
|
// run the basic lighting equation...
|
|
intensity = sgConstantAttenuation;
|
|
intensity += (sgQuadraticAttenuation * distsq);
|
|
if(sgLinearAttenuation > 0.0f)
|
|
intensity += (sgLinearAttenuation * mSqrt(distsq));
|
|
}
|
|
else
|
|
{
|
|
intensity = 1.0f;
|
|
}
|
|
|
|
// this seems fine...
|
|
if(intensity <= 0.0f)
|
|
return false;
|
|
|
|
intensity = 1.0f / intensity;
|
|
|
|
ColorF col = sgLight->mColor * intensity;
|
|
if((col.red < SG_MIN_LEXEL_INTENSITY) && (col.green < SG_MIN_LEXEL_INTENSITY) &&
|
|
(col.blue < SG_MIN_LEXEL_INTENSITY))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
F32 sgLightingModelGLBase::sgGetMaxRadius(bool speedoverquality, bool glstyle)
|
|
{
|
|
AssertFatal((sgStateSet == true), "sgLightingModel: State not properly set.");
|
|
|
|
if((sgLight->mType == LightInfo::Vector) || (sgLight->mType == LightInfo::Ambient))
|
|
return 1000000.0f;
|
|
|
|
// get started...
|
|
// don't use F32_MAX, this value will be added to stuff...
|
|
const F32 infinity = 1.0e+6F;
|
|
F32 adjustedvalue;
|
|
if(speedoverquality)
|
|
adjustedvalue = (1.0f / SG_MIN_LEXEL_INTENSITY_SPEED_OVER_QUALITY) - sgConstantAttenuation;
|
|
else
|
|
adjustedvalue = (1.0f / SG_MIN_LEXEL_INTENSITY) - sgConstantAttenuation;
|
|
|
|
// early out?
|
|
if(adjustedvalue <= 0.0f)
|
|
return 0.0f;
|
|
|
|
// this is the default even when L and Q are both populated...
|
|
if(sgLinearAttenuation > 0.0f)
|
|
return adjustedvalue / sgLinearAttenuation;
|
|
|
|
if(sgQuadraticAttenuation > 0.0f)
|
|
return mSqrt(adjustedvalue / sgQuadraticAttenuation);
|
|
|
|
if(sgConstantAttenuation > 0.0f)
|
|
return infinity;
|
|
|
|
return 0.0f;
|
|
}
|
|
|
|
void sgLightingModelGLBase::sgSetState(LightInfo *light)
|
|
{
|
|
sgLightingModel::sgSetState(light);
|
|
|
|
sgConstantAttenuation = 0.0f;
|
|
sgLinearAttenuation = 0.0f;
|
|
sgQuadraticAttenuation = 0.0f;
|
|
|
|
sgLightParamDiffuse = Point4F(light->mColor.red * light->sgDTSLightingOcclusionAdjust,
|
|
light->mColor.green * light->sgDTSLightingOcclusionAdjust,
|
|
light->mColor.blue * light->sgDTSLightingOcclusionAdjust,
|
|
1.0f);
|
|
|
|
sgLightParamAmbient = Point4F(light->mAmbient.red, light->mAmbient.green, light->mAmbient.blue, 1.0f);
|
|
sgLightParamPosition = Point4F(light->mPos.x, light->mPos.y, light->mPos.z, 1.0f);
|
|
sgLightParamDirection = Point4F(-light->mDirection.x, -light->mDirection.y, -light->mDirection.z, 0.0f);
|
|
}
|
|
|
|
void sgLightingModelGLBase::sgLightingGL(S32 gllight)
|
|
{
|
|
sgLightingModel::sgLightingGL(gllight);
|
|
|
|
const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
|
|
if((sgLight->mType == LightInfo::Vector) || (sgLight->mType == LightInfo::Ambient))
|
|
{
|
|
F32 ambientFactor = (sgLightParamAmbient[0] + sgLightParamAmbient[1] + sgLightParamAmbient[2]) / 3.0f;
|
|
F32 factor = mClampF(1.0f - ambientFactor, 0.f, 1.f);
|
|
|
|
// attenuate (for in shadow...)
|
|
sgLightParamDiffuse.x *= factor;
|
|
sgLightParamDiffuse.y *= factor;
|
|
sgLightParamDiffuse.z *= factor;
|
|
|
|
glLightfv(gllight, GL_POSITION, (const GLfloat*)&sgLightParamDirection.x);
|
|
|
|
// do not add this back in!!!
|
|
// the DX wrapper is a bastard!!!
|
|
//glLightfv(gllight, GL_SPOT_DIRECTION, (const GLfloat*)black);
|
|
|
|
glLightfv(gllight, GL_DIFFUSE, (const GLfloat*)&sgLightParamDiffuse.x);
|
|
glLightfv(gllight, GL_AMBIENT, (const GLfloat*)&sgLightParamAmbient.x);
|
|
glLightfv(gllight, GL_SPECULAR, (const GLfloat*)black);
|
|
|
|
LightManager::sgSetAmbientSelfIllumination(sgLight, &sgLightParamDiffuse.x, &sgLightParamAmbient.x);
|
|
|
|
glLightf(gllight, GL_SPOT_CUTOFF, 180.f);
|
|
|
|
glLightf(gllight, GL_CONSTANT_ATTENUATION, 0.0f);
|
|
glLightf(gllight, GL_QUADRATIC_ATTENUATION, 0.0f);
|
|
glLightf(gllight, GL_LINEAR_ATTENUATION, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
glLightfv(gllight, GL_POSITION, (const GLfloat*)&sgLightParamPosition.x);
|
|
|
|
// must be here and only set spots!!!
|
|
// the DX wrapper is a bastard!!!
|
|
if((sgLight->mType == LightInfo::SGStaticSpot) || (sgLight->mType == LightInfo::Spot))
|
|
glLightfv(gllight, GL_SPOT_DIRECTION, (const GLfloat*)&sgLightParamDirection.x);
|
|
|
|
glLightfv(gllight, GL_DIFFUSE, (const GLfloat*)&sgLightParamDiffuse.x);
|
|
glLightfv(gllight, GL_AMBIENT, (const GLfloat*)black);
|
|
glLightfv(gllight, GL_SPECULAR, (const GLfloat*)black);
|
|
|
|
if((sgLight->mType == LightInfo::SGStaticSpot) || (sgLight->mType == LightInfo::Spot))
|
|
glLightf(gllight, GL_SPOT_CUTOFF, (sgLight->sgSpotAngle * 0.5f));
|
|
else
|
|
glLightf(gllight, GL_SPOT_CUTOFF, 180.f);
|
|
|
|
glLightf(gllight, GL_CONSTANT_ATTENUATION, sgConstantAttenuation);
|
|
glLightf(gllight, GL_QUADRATIC_ATTENUATION, sgQuadraticAttenuation);
|
|
glLightf(gllight, GL_LINEAR_ATTENUATION, sgLinearAttenuation);
|
|
}
|
|
}
|
|
|
|
void sgLightingModelGLBase::sgInitStateLM()
|
|
{
|
|
sgLightingModel::sgInitStateLM();
|
|
|
|
spotanglecos = mCos(mDegToRad(sgLight->sgSpotAngle * 0.5f));
|
|
spotamountinner = 1.0f - spotanglecos;
|
|
spotamountouter = spotanglecos;
|
|
}
|
|
|
|
void sgLightingModelGLBase::sgLightingLM(const Point3F &point, VectorF normal, ColorF &diffuse, ColorF &ambient, Point3F &lightingnormal)
|
|
{
|
|
sgLightingModel::sgLightingLM(point, normal, diffuse, ambient, lightingnormal);
|
|
|
|
F32 anglefalloff = 0.0f;
|
|
|
|
// for speed set on exit - wrong! too often unset...
|
|
// do this in lightmap...
|
|
//diffuse = ColorF(0.0, 0.0, 0.0);
|
|
//ambient = ColorF(0.0, 0.0, 0.0);
|
|
//lightingnormal = Point3F(0.0, 0.0, 0.0);
|
|
|
|
// get the lighting vector squared...
|
|
if(sgLight->mType == LightInfo::Vector)
|
|
lightingnormal = sgLight->mDirection * -1.0f;
|
|
else
|
|
lightingnormal = sgLight->mPos - point;
|
|
|
|
// early out 1 - is surface facing light without double sided ambient (for terrain)?
|
|
anglefalloff = mDot(lightingnormal, normal);
|
|
if((anglefalloff <= 0.0f) && !(sgLight->sgDoubleSidedAmbient &&
|
|
((sgLight->sgLocalAmbientAmount >= SG_LIGHTING_MIN_CUTOFF) ||
|
|
(sgLight->mType == LightInfo::Vector))))
|
|
{
|
|
// do this in lightmap...
|
|
//diffuse = ColorF(0.0, 0.0, 0.0);
|
|
//ambient = ColorF(0.0, 0.0, 0.0);
|
|
//lightingnormal = Point3F(0.0, 0.0, 0.0);
|
|
return;
|
|
}
|
|
|
|
F32 dist = 0.0f;
|
|
F32 distsq = 0.0f;
|
|
F32 distfalloff = 1.0f;
|
|
F32 spotlightangle = 1.0f;
|
|
|
|
// so far so good - now get the dist falloff...
|
|
if(sgLight->mType != LightInfo::Vector)
|
|
{
|
|
bool didsqrt = false;
|
|
// need this...
|
|
distsq = lightingnormal.lenSquared();
|
|
// only need now for linear...
|
|
if(sgLinearAttenuation > 0.0f)
|
|
{
|
|
dist = mSqrt(distsq);
|
|
didsqrt = true;
|
|
}
|
|
|
|
distfalloff = (sgConstantAttenuation + (sgLinearAttenuation * dist) + (sgQuadraticAttenuation * distsq));
|
|
if(distfalloff > 0.0f)
|
|
distfalloff = 1.0f / distfalloff;
|
|
distfalloff = getMax(distfalloff, 0.0f);
|
|
|
|
// early out 2 - too far away?
|
|
if(distfalloff <= SG_LIGHTING_MIN_CUTOFF)
|
|
{
|
|
// do this in lightmap...
|
|
//diffuse = ColorF(0.0, 0.0, 0.0);
|
|
//ambient = ColorF(0.0, 0.0, 0.0);
|
|
//lightingnormal = Point3F(0.0, 0.0, 0.0);
|
|
return;
|
|
}
|
|
|
|
// get it now...
|
|
if(!didsqrt)
|
|
dist = mSqrt(distsq);
|
|
|
|
// normalize...
|
|
if(dist != 0.0f)
|
|
lightingnormal /= dist;
|
|
|
|
// safe to bailout here, ambient only follows spot...
|
|
if(sgLight->mType == LightInfo::SGStaticSpot)
|
|
{
|
|
spotlightangle = mDot(lightingnormal, sgLight->mDirection);
|
|
if(spotlightangle < spotanglecos)
|
|
{
|
|
//diffuse = ColorF(0.0, 0.0, 0.0);
|
|
//ambient = ColorF(0.0, 0.0, 0.0);
|
|
//lightingnormal = Point3F(0.0, 0.0, 0.0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// values coming from terrain are not normalized...
|
|
// lightingnormal is already normalized...
|
|
if((anglefalloff > 0.0f) && sgLight->sgUseNormals)
|
|
{
|
|
normal.normalize();
|
|
anglefalloff = mDot(lightingnormal, normal);
|
|
}
|
|
anglefalloff = getMax(getMin(anglefalloff, 1.0f), 0.0f);
|
|
|
|
|
|
if(sgLight->mType == LightInfo::SGStaticSpot)
|
|
{
|
|
// apply the spotlight lighting model...
|
|
spotlightangle = mClampF(((spotlightangle - spotamountouter) / spotamountinner), 0.0f, 1.0f);
|
|
|
|
if(sgLight->sgSmoothSpotLight)
|
|
spotlightangle *= getMin((spotlightangle * 1.2f), 1.0f);
|
|
}
|
|
|
|
|
|
if((sgLight->mType == LightInfo::Vector) && (anglefalloff < 0.0f))
|
|
anglefalloff = anglefalloff;
|
|
|
|
|
|
F32 ambientlightingamount = distfalloff * spotlightangle;
|
|
|
|
if(anglefalloff > 0.0f)
|
|
{
|
|
F32 diffuselightingamount = ambientlightingamount;
|
|
if(sgLight->sgUseNormals)
|
|
diffuselightingamount *= anglefalloff;
|
|
|
|
diffuselightingamount *= (1 - sgLight->sgLocalAmbientAmount);
|
|
diffuselightingamount = getMax(getMin(diffuselightingamount, 1.0f), 0.0f);
|
|
diffuse = sgLight->mColor * diffuselightingamount;
|
|
}
|
|
|
|
if(sgLight->sgDoubleSidedAmbient || (anglefalloff > 0.0f))
|
|
{
|
|
if(sgLight->mType == LightInfo::Vector)
|
|
{
|
|
ambient = sgLight->mAmbient;
|
|
}
|
|
else
|
|
{
|
|
ambientlightingamount *= sgLight->sgLocalAmbientAmount;
|
|
ambientlightingamount = getMax(getMin(ambientlightingamount, 1.0f), 0.0f);
|
|
ambient = sgLight->mColor * ambientlightingamount;
|
|
}
|
|
}
|
|
|
|
|
|
/*Point3F lightvectorsq;
|
|
Point3F lightvector;
|
|
Point3F lightvectorfordist;
|
|
F32 spotlightingangle;
|
|
|
|
//F32 anglefalloff = 0;
|
|
F32 dist;
|
|
F32 distsq;
|
|
|
|
// for speed set on exit...
|
|
diffuse = ColorF(0.0, 0.0, 0.0);
|
|
ambient = ColorF(0.0, 0.0, 0.0);
|
|
lightingnormal = Point3F(0.0, 0.0, 0.0);
|
|
|
|
// get light vector...
|
|
if(sgLight->mType == LightInfo::Vector)
|
|
lightvector = sgLight->mDirection * -1;
|
|
else
|
|
{
|
|
lightvector = sgLight->mPos - point;
|
|
// need this later...
|
|
lightvectorfordist = lightvector;
|
|
// vector lights are already normallized...
|
|
lightvector.normalize();
|
|
}
|
|
|
|
lightingnormal = lightvector;
|
|
|
|
// is it a spotlight? is it pointing this way?
|
|
if(sgLight->mType == LightInfo::SGStaticSpot)
|
|
{
|
|
spotlightingangle = mDot(lightvector, sgLight->mDirection);
|
|
if(spotlightingangle < spotanglecos)
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// default...
|
|
spotlightingangle = 1.0;
|
|
}
|
|
|
|
// get the attenuation info...
|
|
if(sgLight->mType != LightInfo::Vector)
|
|
{
|
|
if(sgQuadraticAttenuation > 0.0f)
|
|
distsq = lightvectorfordist.lenSquared();
|
|
|
|
// should never use linear...
|
|
if(sgLinearAttenuation > 0.0f)
|
|
dist = lightvectorfordist.len();
|
|
}
|
|
|
|
// get the lighting angle amount...
|
|
F32 angleamount = mDot(lightvector, normal);
|
|
F32 lightamount = angleamount;
|
|
F32 lightfalloff = 1.0;
|
|
lightamount = getMax(getMin(lightamount, 1.0f), 0.0f);
|
|
|
|
if(sgLight->mType != LightInfo::Vector)
|
|
{
|
|
// ahhh the lighting model...
|
|
lightfalloff = (sgConstantAttenuation + (sgLinearAttenuation * dist) + (sgQuadraticAttenuation * distsq));
|
|
if(lightfalloff != 0.0f)
|
|
lightfalloff = 1 / lightfalloff;
|
|
lightfalloff = getMax(lightfalloff, 0.0f);
|
|
|
|
if(sgLight->mType == LightInfo::SGStaticSpot)
|
|
{
|
|
// apply the spotlight lighting model...
|
|
spotlightingangle = mClampF(((spotlightingangle - spotamountouter) / spotamountinner), 0.0f, 1.0f);
|
|
|
|
if(sgLight->sgLightInfoData.sgSmoothSpotLight)
|
|
spotlightingangle *= getMin((spotlightingangle * 1.2), 1.0);
|
|
|
|
lightfalloff *= spotlightingangle;
|
|
}
|
|
|
|
lightamount *= lightfalloff;
|
|
}
|
|
|
|
lightamount *= (1 - sgLight->sgLightInfoData.sgLocalAmbientAmount);
|
|
lightamount = getMax(getMin(lightamount, 1.0f), 0.0f);
|
|
diffuse = sgLight->mColor * lightamount;
|
|
|
|
if(sgLight->sgLightInfoData.sgDoubleSidedAmbient || (angleamount > 0.0f))
|
|
{
|
|
lightfalloff *= sgLight->sgLightInfoData.sgLocalAmbientAmount;
|
|
lightfalloff = getMax(getMin(lightfalloff, 1.0f), 0.0f);
|
|
ambient = sgLight->mColor * lightfalloff;
|
|
}*/
|
|
}
|