mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-26 05:41:42 +00:00
- add spotlight support
This commit is contained in:
parent
8bea68f6af
commit
8b290752c6
6 changed files with 79 additions and 39 deletions
|
@ -223,6 +223,7 @@ struct IntThing
|
||||||
char special;
|
char special;
|
||||||
char args[5];
|
char args[5];
|
||||||
|
|
||||||
|
short pitch; // UDMF
|
||||||
float height; // UDMF
|
float height; // UDMF
|
||||||
|
|
||||||
TArray<UDMFKey> props;
|
TArray<UDMFKey> props;
|
||||||
|
@ -278,7 +279,8 @@ struct thingLight_t
|
||||||
kexVec2 origin;
|
kexVec2 origin;
|
||||||
kexVec3 rgb;
|
kexVec3 rgb;
|
||||||
float intensity;
|
float intensity;
|
||||||
float falloff;
|
float innerAngleCos;
|
||||||
|
float outerAngleCos;
|
||||||
float height;
|
float height;
|
||||||
float radius;
|
float radius;
|
||||||
bool bCeiling;
|
bool bCeiling;
|
||||||
|
|
|
@ -130,6 +130,7 @@ void FProcessor::LoadThings ()
|
||||||
Level.Things[i].args[2] = Things[i].args[2];
|
Level.Things[i].args[2] = Things[i].args[2];
|
||||||
Level.Things[i].args[3] = Things[i].args[3];
|
Level.Things[i].args[3] = Things[i].args[3];
|
||||||
Level.Things[i].args[4] = Things[i].args[4];
|
Level.Things[i].args[4] = Things[i].args[4];
|
||||||
|
Level.Things[i].pitch = 0;
|
||||||
}
|
}
|
||||||
delete[] Things;
|
delete[] Things;
|
||||||
}
|
}
|
||||||
|
@ -153,6 +154,7 @@ void FProcessor::LoadThings ()
|
||||||
Level.Things[i].args[2] = 0;
|
Level.Things[i].args[2] = 0;
|
||||||
Level.Things[i].args[3] = 0;
|
Level.Things[i].args[3] = 0;
|
||||||
Level.Things[i].args[4] = 0;
|
Level.Things[i].args[4] = 0;
|
||||||
|
Level.Things[i].pitch = 0;
|
||||||
}
|
}
|
||||||
delete[] mt;
|
delete[] mt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,8 @@ fixed_t CheckFixed(const char *key)
|
||||||
|
|
||||||
void FProcessor::ParseThing(IntThing *th)
|
void FProcessor::ParseThing(IntThing *th)
|
||||||
{
|
{
|
||||||
|
th->pitch = 0;
|
||||||
|
|
||||||
SC_MustGetStringName("{");
|
SC_MustGetStringName("{");
|
||||||
while (!SC_CheckString("}"))
|
while (!SC_CheckString("}"))
|
||||||
{
|
{
|
||||||
|
@ -179,6 +181,10 @@ void FProcessor::ParseThing(IntThing *th)
|
||||||
{
|
{
|
||||||
th->angle = (short)CheckInt(key);
|
th->angle = (short)CheckInt(key);
|
||||||
}
|
}
|
||||||
|
if (!stricmp(key, "pitch"))
|
||||||
|
{
|
||||||
|
th->pitch = (short)CheckInt(key);
|
||||||
|
}
|
||||||
if (!stricmp(key, "type"))
|
if (!stricmp(key, "type"))
|
||||||
{
|
{
|
||||||
th->type = (short)CheckInt(key);
|
th->type = (short)CheckInt(key);
|
||||||
|
|
|
@ -238,19 +238,22 @@ bool kexLightmapBuilder::EmitFromCeiling(kexTrace &trace, const surface_t *surfa
|
||||||
// and against all nearby thing lights
|
// and against all nearby thing lights
|
||||||
//
|
//
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T smoothstep(const T edge0, const T edge1, const T x)
|
||||||
|
{
|
||||||
|
auto t = clamp<T>((x - edge0) / (edge1 - edge0), 0.0, 1.0);
|
||||||
|
return t * t * (3.0 - 2.0 * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float radians(float degrees)
|
||||||
|
{
|
||||||
|
return degrees * 3.14159265359f / 180.0f;
|
||||||
|
}
|
||||||
|
|
||||||
kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &origin, surface_t *surface)
|
kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &origin, surface_t *surface)
|
||||||
{
|
{
|
||||||
kexVec3 lightOrigin;
|
kexPlane plane = surface->plane;
|
||||||
kexVec3 dir;
|
kexVec3 color(0.0f, 0.0f, 0.0f);
|
||||||
kexVec3 color;
|
|
||||||
kexPlane plane;
|
|
||||||
float dist;
|
|
||||||
float radius;
|
|
||||||
float intensity;
|
|
||||||
float colorAdd;
|
|
||||||
|
|
||||||
plane = surface->plane;
|
|
||||||
color.Clear();
|
|
||||||
|
|
||||||
// check all thing lights
|
// check all thing lights
|
||||||
for(unsigned int i = 0; i < map->thingLights.Size(); i++)
|
for(unsigned int i = 0; i < map->thingLights.Size(); i++)
|
||||||
|
@ -263,11 +266,13 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lightOrigin.Set(tl->origin.x,
|
float originZ;
|
||||||
tl->origin.y,
|
if (!tl->bCeiling)
|
||||||
!tl->bCeiling ?
|
originZ = tl->sector->floorplane.zAt(tl->origin.x, tl->origin.y) + tl->height;
|
||||||
tl->sector->data.floorheight + tl->height :
|
else
|
||||||
tl->sector->data.ceilingheight - tl->height);
|
originZ = tl->sector->ceilingplane.zAt(tl->origin.x, tl->origin.y) - tl->height;
|
||||||
|
|
||||||
|
kexVec3 lightOrigin(tl->origin.x, tl->origin.y, originZ);
|
||||||
|
|
||||||
if(plane.Distance(lightOrigin) - plane.d < 0)
|
if(plane.Distance(lightOrigin) - plane.d < 0)
|
||||||
{
|
{
|
||||||
|
@ -275,8 +280,8 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
radius = tl->radius;
|
float radius = tl->radius;
|
||||||
intensity = tl->intensity;
|
float intensity = tl->intensity;
|
||||||
|
|
||||||
if(origin.DistanceSq(lightOrigin) > (radius*radius))
|
if(origin.DistanceSq(lightOrigin) > (radius*radius))
|
||||||
{
|
{
|
||||||
|
@ -284,6 +289,28 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kexVec3 dir = (lightOrigin - origin);
|
||||||
|
float dist = dir.Unit();
|
||||||
|
dir.Normalize();
|
||||||
|
|
||||||
|
float spotAttenuation = 1.0f;
|
||||||
|
if (tl->outerAngleCos > -1.0f)
|
||||||
|
{
|
||||||
|
float negPitch = -radians(tl->mapThing->pitch);
|
||||||
|
float xyLen = std::cosf(negPitch);
|
||||||
|
kexVec3 spotDir;
|
||||||
|
spotDir.x = std::sinf(radians(tl->mapThing->angle)) * xyLen;
|
||||||
|
spotDir.y = std::cosf(radians(tl->mapThing->angle)) * xyLen;
|
||||||
|
spotDir.z = -std::sinf(negPitch);
|
||||||
|
float cosDir = kexVec3::Dot(dir, spotDir);
|
||||||
|
spotAttenuation = smoothstep(tl->outerAngleCos, tl->innerAngleCos, cosDir);
|
||||||
|
if (spotAttenuation <= 0.0f)
|
||||||
|
{
|
||||||
|
// outside spot light
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trace.Trace(lightOrigin, origin);
|
trace.Trace(lightOrigin, origin);
|
||||||
|
|
||||||
if(trace.fraction != 1)
|
if(trace.fraction != 1)
|
||||||
|
@ -292,23 +319,13 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = (lightOrigin - origin);
|
float attenuation = 1.0f - (dist / radius);
|
||||||
dist = dir.Unit();
|
attenuation *= spotAttenuation;
|
||||||
|
attenuation *= plane.Normal().Dot(dir);
|
||||||
dir.Normalize();
|
attenuation *= intensity;
|
||||||
|
|
||||||
float r = MAX(radius - dist, 0.0f);
|
|
||||||
|
|
||||||
colorAdd = ((r * plane.Normal().Dot(dir)) / radius) * intensity;
|
|
||||||
kexMath::Clamp(colorAdd, 0, 1);
|
|
||||||
|
|
||||||
if(tl->falloff != 1)
|
|
||||||
{
|
|
||||||
colorAdd = kexMath::Pow(colorAdd, tl->falloff);
|
|
||||||
}
|
|
||||||
|
|
||||||
// accumulate results
|
// accumulate results
|
||||||
color += tl->rgb * colorAdd;
|
color += tl->rgb * attenuation;
|
||||||
|
|
||||||
tracedTexels++;
|
tracedTexels++;
|
||||||
}
|
}
|
||||||
|
@ -331,9 +348,10 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(surfaceLight->TraceSurface(map, trace, surface, origin, &dist))
|
float attenuation;
|
||||||
|
if(surfaceLight->TraceSurface(map, trace, surface, origin, &attenuation))
|
||||||
{
|
{
|
||||||
color += surfaceLight->GetRGB() * kexMath::Pow(dist * surfaceLight->Intensity(), surfaceLight->FallOff());
|
color += surfaceLight->GetRGB() * attenuation;
|
||||||
|
|
||||||
tracedTexels++;
|
tracedTexels++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,7 +302,7 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa
|
||||||
// light surface will always be fullbright
|
// light surface will always be fullbright
|
||||||
if(surf == surface)
|
if(surf == surface)
|
||||||
{
|
{
|
||||||
*dist = 1;
|
*dist = Intensity();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,7 +426,7 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa
|
||||||
if(!bWall)
|
if(!bWall)
|
||||||
{
|
{
|
||||||
*dist = 1;
|
*dist = 1;
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,5 +451,6 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*dist *= Intensity();
|
||||||
return *dist > 0;
|
return *dist > 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -450,6 +450,8 @@ void FLevel::CreateLights()
|
||||||
uint32_t lightcolor = 0xffffff;
|
uint32_t lightcolor = 0xffffff;
|
||||||
float lightintensity = 1.0f;
|
float lightintensity = 1.0f;
|
||||||
float lightdistance = 0.0f;
|
float lightdistance = 0.0f;
|
||||||
|
float innerAngleCos = -1.0f;
|
||||||
|
float outerAngleCos = -1.0f;
|
||||||
|
|
||||||
for (unsigned int propIndex = 0; propIndex < thing->props.Size(); propIndex++)
|
for (unsigned int propIndex = 0; propIndex < thing->props.Size(); propIndex++)
|
||||||
{
|
{
|
||||||
|
@ -466,6 +468,14 @@ void FLevel::CreateLights()
|
||||||
{
|
{
|
||||||
lightdistance = atof(key.value);
|
lightdistance = atof(key.value);
|
||||||
}
|
}
|
||||||
|
else if (!stricmp(key.key, "lightinnerangle"))
|
||||||
|
{
|
||||||
|
innerAngleCos = std::cosf(atof(key.value) * 3.14159265359f / 180.0f);
|
||||||
|
}
|
||||||
|
else if (!stricmp(key.key, "lightouterangle"))
|
||||||
|
{
|
||||||
|
outerAngleCos = std::cosf(atof(key.value) * 3.14159265359f / 180.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lightdistance > 0.0f && lightintensity > 0.0f && lightcolor != 0)
|
if (lightdistance > 0.0f && lightintensity > 0.0f && lightcolor != 0)
|
||||||
|
@ -480,7 +490,8 @@ void FLevel::CreateLights()
|
||||||
thingLight->rgb.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
thingLight->rgb.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
||||||
thingLight->rgb.z = (lightcolor & 0xff) / 255.0f;
|
thingLight->rgb.z = (lightcolor & 0xff) / 255.0f;
|
||||||
thingLight->intensity = lightintensity;
|
thingLight->intensity = lightintensity;
|
||||||
thingLight->falloff = 1.0f;
|
thingLight->innerAngleCos = max(innerAngleCos, outerAngleCos);
|
||||||
|
thingLight->outerAngleCos = outerAngleCos;
|
||||||
thingLight->radius = lightdistance;
|
thingLight->radius = lightdistance;
|
||||||
thingLight->height = thing->height;
|
thingLight->height = thing->height;
|
||||||
thingLight->bCeiling = false;
|
thingLight->bCeiling = false;
|
||||||
|
|
Loading…
Reference in a new issue