- implement the correct math for area lights

This commit is contained in:
Magnus Norddahl 2018-11-02 23:34:38 +01:00
parent b588b809ea
commit 664be1eca5
3 changed files with 19 additions and 60 deletions

View File

@ -301,11 +301,10 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
{ {
kexLightSurface *surfaceLight = map->lightSurfaces[i]; kexLightSurface *surfaceLight = map->lightSurfaces[i];
float attenuation; float attenuation = surfaceLight->TraceSurface(map, trace, surface, origin);
if (surfaceLight->TraceSurface(map, trace, surface, origin, &attenuation)) if (attenuation > 0.0f)
{ {
color += surfaceLight->GetRGB() * attenuation; color += surfaceLight->GetRGB() * surfaceLight->Intensity() * attenuation;
tracedTexels++; tracedTexels++;
} }
} }

View File

@ -243,23 +243,17 @@ void kexLightSurface::Subdivide(const float divide)
} }
} }
bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surface_t *surf, const kexVec3 &origin, float *dist) float kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surface_t *surf, const kexVec3 &origin)
{ {
kexVec3 normal;
kexVec3 lnormal;
float curDist;
*dist = -M_INFINITY;
// light surface will always be fullbright // light surface will always be fullbright
if (surf == surface) if (surf == surface)
{ {
*dist = Intensity(); return 1.0f;
return true;
} }
lnormal = surface->plane.Normal(); kexVec3 lnormal = surface->plane.Normal();
kexVec3 normal;
if (surf) if (surf)
{ {
normal = surf->plane.Normal(); normal = surf->plane.Normal();
@ -267,7 +261,7 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa
if (normal.Dot(lnormal) > 0) if (normal.Dot(lnormal) > 0)
{ {
// not facing the light surface // not facing the light surface
return false; return 0.0f;
} }
} }
else else
@ -275,8 +269,7 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa
normal = kexVec3::vecUp; normal = kexVec3::vecUp;
} }
// we need to pick the closest sample point on the light surface. what really sucks is float total = 0.0f;
// that we have to trace each one... which could really blow up the compile time
for (unsigned int i = 0; i < origins.Length(); ++i) for (unsigned int i = 0; i < origins.Length(); ++i)
{ {
kexVec3 center = origins[i]; kexVec3 center = origins[i];
@ -289,25 +282,11 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa
continue; continue;
} }
/*if(bWall) kexVec3 dir = (origin - center).Normalize();
{ float attenuation = dir.Dot(lnormal);
angle = (origin - center).ToVec2().Normalize().Dot(lnormal.ToVec2());
}
else
{
kexVec3 dir = (origin - center).Normalize();
if(surf) if (attenuation <= 0.0f)
{ continue; // not even facing the light surface
if(normal.Dot(dir) >= 0)
{
// not even facing the light surface
continue;
}
}
angle = dir.Dot(lnormal);
}*/
if (bWall) if (bWall)
{ {
@ -324,36 +303,17 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa
// case the start/end points are directly on or inside the surface // case the start/end points are directly on or inside the surface
trace.Trace(center + lnormal, origin + normal); trace.Trace(center + lnormal, origin + normal);
if (trace.fraction != 1) if (trace.fraction < 1.0f)
{ {
// something is obstructing it // something is obstructing it
continue; continue;
} }
float d = origin.Distance(center); float d = origin.Distance(center);
attenuation *= 1.0f - d / (distance * 2.0f); // 2.0 because gzdoom's dynlights do this and we want them to match
curDist = 1.0f - d / (distance * 2.0f); // 2.0 because gzdoom's dynlights do this and we want them to match if (attenuation > 0.0f)
if (curDist < 0.0f) curDist = 0.0f; total += attenuation;
if (curDist >= 1)
{
curDist = 1;
// might get large unlit gaps near the surface. this looks a lot worse for
// non-wall light surfaces so just clamp to full bright and exit out.
if (!bWall)
{
*dist = 1;
break;
}
}
if (curDist > *dist)
{
*dist = curDist;
}
} }
*dist *= Intensity(); return total / origins.Length();
return *dist > 0;
} }

View File

@ -42,7 +42,7 @@ public:
void Init(const surfaceLightDef &lightSurfaceDef, surface_t *surface, const bool bWall, const bool bNoCenterPoint); void Init(const surfaceLightDef &lightSurfaceDef, surface_t *surface, const bool bWall, const bool bNoCenterPoint);
void Subdivide(const float divide); void Subdivide(const float divide);
void CreateCenterOrigin(); void CreateCenterOrigin();
bool TraceSurface(FLevel *doomMap, kexTrace &trace, const surface_t *surface, const kexVec3 &origin, float *dist); float TraceSurface(FLevel *doomMap, kexTrace &trace, const surface_t *surface, const kexVec3 &origin);
const float Distance() const { return distance; } const float Distance() const { return distance; }
const float Intensity() const { return intensity; } const float Intensity() const { return intensity; }