Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lighting Attenuation #2471

Merged
merged 2 commits into from
Jun 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
199 changes: 65 additions & 134 deletions Source/Core/VideoBackends/Software/TransformUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,42 +208,35 @@ static inline float SafeDivide(float n, float d)
return (d==0) ? (n>0?1:0) : n/d;
}

static void LightColor(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, Vec3 &lightCol)
static float CalculateLightAttn(const LightPointer *light, Vec3* _ldir, const Vec3 &normal, const LitChannel &chan)
{
const LightPointer *light = (const LightPointer*)&xfmem.lights[lightNum];
float attn = 1.0f;
Vec3& ldir = *_ldir;

if (!(chan.attnfunc & 1))
switch (chan.attnfunc)
{
// atten disabled
switch (chan.diffusefunc)
case LIGHTATTN_NONE:
case LIGHTATTN_DIR:
{
case LIGHTDIF_NONE:
AddIntegerColor(light->color, lightCol);
break;
case LIGHTDIF_SIGN:
{
Vec3 ldir = (light->pos - pos).Normalized();
float diffuse = ldir * normal;
AddScaledIntegerColor(light->color, diffuse, lightCol);
}
break;
case LIGHTDIF_CLAMP:
{
Vec3 ldir = (light->pos - pos).Normalized();
float diffuse = std::max(0.0f, ldir * normal);
AddScaledIntegerColor(light->color, diffuse, lightCol);
}
break;
default: _assert_(0);
ldir = ldir.Normalized();
if (ldir == Vec3(0.0f, 0.0f, 0.0f))
ldir = normal;
break;
}
}
else // spec and spot
{
// not sure about divide by zero checks
Vec3 ldir = light->pos - pos;
float attn;

if (chan.attnfunc == 3) // spot
case LIGHTATTN_SPEC:
{
ldir = ldir.Normalized();
attn = (ldir * normal) >= 0.0 ? std::max(0.0f, light->dir * normal) : 0;
Vec3 attLen = Vec3(1.0, attn, attn*attn);
Vec3 cosAttn = light->cosatt;
Vec3 distAttn = light->distatt;
if (chan.diffusefunc != LIGHTDIF_NONE)
distAttn = distAttn.Normalized();

attn = SafeDivide(std::max(0.0f, attLen * cosAttn), attLen * distAttn);
break;
}
case LIGHTATTN_SPOT:
{
float dist2 = ldir.Length2();
float dist = sqrtf(dist2);
Expand All @@ -253,122 +246,60 @@ static void LightColor(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const L
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
attn = SafeDivide(std::max(0.0f, cosAtt), distAtt);
break;
}
else if (chan.attnfunc == 1) // specular
{
// donko - what is going on here? 655.36 is a guess but seems about right.
attn = (light->pos * normal) > -655.36 ? std::max(0.0f, (light->dir * normal)) : 0;
ldir.set(1.0f, attn, attn * attn);

float cosAtt = std::max(0.0f, light->cosatt * ldir);
float distAtt = light->distatt * ldir;
attn = SafeDivide(std::max(0.0f, cosAtt), distAtt);
}
else
{
default:
PanicAlert("LightColor");
return;
}

switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
AddScaledIntegerColor(light->color, attn, lightCol);
break;
case LIGHTDIF_SIGN:
{
float difAttn = ldir * normal;
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
}
break;

case LIGHTDIF_CLAMP:
{
float difAttn = std::max(0.0f, ldir * normal);
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
}
break;
default: _assert_(0);
}
}

return attn;
}

static void LightAlpha(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, float &lightCol)
static void LightColor(const Vec3 &pos, const Vec3 &normal, u8 lightNum, LitChannel &chan, Vec3 &lightCol)
{
const LightPointer *light = (const LightPointer*)&xfmem.lights[lightNum];

if (!(chan.attnfunc & 1))
Vec3 ldir = light->pos - pos;
float attn = CalculateLightAttn(light, &ldir, normal, chan);

float difAttn = ldir * normal;
switch (chan.diffusefunc)
{
// atten disabled
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
lightCol += light->color[0];
break;
case LIGHTDIF_SIGN:
{
Vec3 ldir = (light->pos - pos).Normalized();
float diffuse = ldir * normal;
lightCol += light->color[0] * diffuse;
}
break;
case LIGHTDIF_CLAMP:
{
Vec3 ldir = (light->pos - pos).Normalized();
float diffuse = std::max(0.0f, ldir * normal);
lightCol += light->color[0] * diffuse;
}
break;
default: _assert_(0);
}
case LIGHTDIF_NONE:
AddScaledIntegerColor(light->color, attn, lightCol);
break;
case LIGHTDIF_SIGN:
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
break;
case LIGHTDIF_CLAMP:
difAttn = std::max(0.0f, difAttn);
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
break;
default: _assert_(0);
}
else // spec and spot
{
Vec3 ldir = light->pos - pos;
float attn;

if (chan.attnfunc == 3) // spot
{
float dist2 = ldir.Length2();
float dist = sqrtf(dist2);
ldir = ldir / dist;
attn = std::max(0.0f, ldir * light->dir);
}

float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
attn = SafeDivide(std::max(0.0f, cosAtt), distAtt);
}
else /* if (chan.attnfunc == 1) */ // specular
{
// donko - what is going on here? 655.36 is a guess but seems about right.
attn = (light->pos * normal) > -655.36 ? std::max(0.0f, (light->dir * normal)) : 0;
ldir.set(1.0f, attn, attn * attn);
static void LightAlpha(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, float &lightCol)
{
const LightPointer *light = (const LightPointer*)&xfmem.lights[lightNum];

float cosAtt = light->cosatt * ldir;
float distAtt = light->distatt * ldir;
attn = SafeDivide(std::max(0.0f, cosAtt), distAtt);
}
Vec3 ldir = light->pos - pos;
float attn = CalculateLightAttn(light, &ldir, normal, chan);

switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
lightCol += light->color[0] * attn;
break;
case LIGHTDIF_SIGN:
{
float difAttn = ldir * normal;
lightCol += light->color[0] * attn * difAttn;
}
break;

case LIGHTDIF_CLAMP:
{
float difAttn = std::max(0.0f, ldir * normal);
lightCol += light->color[0] * attn * difAttn;
}
break;
default: _assert_(0);
}
float difAttn = ldir * normal;
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
lightCol += light->color[0] * attn;
break;
case LIGHTDIF_SIGN:
lightCol += light->color[0] * attn * difAttn;
break;
case LIGHTDIF_CLAMP:
difAttn = std::max(0.0f, difAttn);
lightCol += light->color[0] * attn * difAttn;
break;
default: _assert_(0);
}
}

Expand Down
4 changes: 3 additions & 1 deletion Source/Core/VideoCommon/LightingShaderGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
case LIGHTATTN_NONE:
case LIGHTATTN_DIR:
object.Write("ldir = normalize(" LIGHT_POS".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(index));
object.Write("attn = 1.0f;\n");
object.Write("attn = 1.0;\n");
object.Write("if (length(ldir) == 0.0)\n\t ldir = _norm0;\n");
break;
case LIGHTATTN_SPEC:
object.Write("ldir = normalize(" LIGHT_POS".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(index));
Expand All @@ -82,6 +83,7 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
object.Write("attn = max(0.0, " LIGHT_COSATT".x + " LIGHT_COSATT".y*attn + " LIGHT_COSATT".z*attn*attn) / dot(" LIGHT_DISTATT".xyz, float3(1.0,dist,dist2));\n",
LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index), LIGHT_DISTATT_PARAMS(index));
break;
default: _assert_(0);
}

switch (chan.diffusefunc)
Expand Down