mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-25 21:31:32 +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 args[5];
|
||||
|
||||
short pitch; // UDMF
|
||||
float height; // UDMF
|
||||
|
||||
TArray<UDMFKey> props;
|
||||
|
@ -278,7 +279,8 @@ struct thingLight_t
|
|||
kexVec2 origin;
|
||||
kexVec3 rgb;
|
||||
float intensity;
|
||||
float falloff;
|
||||
float innerAngleCos;
|
||||
float outerAngleCos;
|
||||
float height;
|
||||
float radius;
|
||||
bool bCeiling;
|
||||
|
|
|
@ -130,6 +130,7 @@ void FProcessor::LoadThings ()
|
|||
Level.Things[i].args[2] = Things[i].args[2];
|
||||
Level.Things[i].args[3] = Things[i].args[3];
|
||||
Level.Things[i].args[4] = Things[i].args[4];
|
||||
Level.Things[i].pitch = 0;
|
||||
}
|
||||
delete[] Things;
|
||||
}
|
||||
|
@ -153,6 +154,7 @@ void FProcessor::LoadThings ()
|
|||
Level.Things[i].args[2] = 0;
|
||||
Level.Things[i].args[3] = 0;
|
||||
Level.Things[i].args[4] = 0;
|
||||
Level.Things[i].pitch = 0;
|
||||
}
|
||||
delete[] mt;
|
||||
}
|
||||
|
|
|
@ -158,6 +158,8 @@ fixed_t CheckFixed(const char *key)
|
|||
|
||||
void FProcessor::ParseThing(IntThing *th)
|
||||
{
|
||||
th->pitch = 0;
|
||||
|
||||
SC_MustGetStringName("{");
|
||||
while (!SC_CheckString("}"))
|
||||
{
|
||||
|
@ -179,6 +181,10 @@ void FProcessor::ParseThing(IntThing *th)
|
|||
{
|
||||
th->angle = (short)CheckInt(key);
|
||||
}
|
||||
if (!stricmp(key, "pitch"))
|
||||
{
|
||||
th->pitch = (short)CheckInt(key);
|
||||
}
|
||||
if (!stricmp(key, "type"))
|
||||
{
|
||||
th->type = (short)CheckInt(key);
|
||||
|
|
|
@ -238,19 +238,22 @@ bool kexLightmapBuilder::EmitFromCeiling(kexTrace &trace, const surface_t *surfa
|
|||
// 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 lightOrigin;
|
||||
kexVec3 dir;
|
||||
kexVec3 color;
|
||||
kexPlane plane;
|
||||
float dist;
|
||||
float radius;
|
||||
float intensity;
|
||||
float colorAdd;
|
||||
|
||||
plane = surface->plane;
|
||||
color.Clear();
|
||||
kexPlane plane = surface->plane;
|
||||
kexVec3 color(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// check all thing lights
|
||||
for(unsigned int i = 0; i < map->thingLights.Size(); i++)
|
||||
|
@ -263,11 +266,13 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
|||
continue;
|
||||
}
|
||||
|
||||
lightOrigin.Set(tl->origin.x,
|
||||
tl->origin.y,
|
||||
!tl->bCeiling ?
|
||||
tl->sector->data.floorheight + tl->height :
|
||||
tl->sector->data.ceilingheight - tl->height);
|
||||
float originZ;
|
||||
if (!tl->bCeiling)
|
||||
originZ = tl->sector->floorplane.zAt(tl->origin.x, tl->origin.y) + tl->height;
|
||||
else
|
||||
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)
|
||||
{
|
||||
|
@ -275,8 +280,8 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
|||
continue;
|
||||
}
|
||||
|
||||
radius = tl->radius;
|
||||
intensity = tl->intensity;
|
||||
float radius = tl->radius;
|
||||
float intensity = tl->intensity;
|
||||
|
||||
if(origin.DistanceSq(lightOrigin) > (radius*radius))
|
||||
{
|
||||
|
@ -284,6 +289,28 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
|||
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);
|
||||
|
||||
if(trace.fraction != 1)
|
||||
|
@ -292,23 +319,13 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
|||
continue;
|
||||
}
|
||||
|
||||
dir = (lightOrigin - origin);
|
||||
dist = dir.Unit();
|
||||
|
||||
dir.Normalize();
|
||||
|
||||
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);
|
||||
}
|
||||
float attenuation = 1.0f - (dist / radius);
|
||||
attenuation *= spotAttenuation;
|
||||
attenuation *= plane.Normal().Dot(dir);
|
||||
attenuation *= intensity;
|
||||
|
||||
// accumulate results
|
||||
color += tl->rgb * colorAdd;
|
||||
color += tl->rgb * attenuation;
|
||||
|
||||
tracedTexels++;
|
||||
}
|
||||
|
@ -331,9 +348,10 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
|||
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++;
|
||||
}
|
||||
|
|
|
@ -302,7 +302,7 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa
|
|||
// light surface will always be fullbright
|
||||
if(surf == surface)
|
||||
{
|
||||
*dist = 1;
|
||||
*dist = Intensity();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -426,7 +426,7 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa
|
|||
if(!bWall)
|
||||
{
|
||||
*dist = 1;
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -451,5 +451,6 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa
|
|||
}
|
||||
}
|
||||
|
||||
*dist *= Intensity();
|
||||
return *dist > 0;
|
||||
}
|
||||
|
|
|
@ -450,6 +450,8 @@ void FLevel::CreateLights()
|
|||
uint32_t lightcolor = 0xffffff;
|
||||
float lightintensity = 1.0f;
|
||||
float lightdistance = 0.0f;
|
||||
float innerAngleCos = -1.0f;
|
||||
float outerAngleCos = -1.0f;
|
||||
|
||||
for (unsigned int propIndex = 0; propIndex < thing->props.Size(); propIndex++)
|
||||
{
|
||||
|
@ -466,6 +468,14 @@ void FLevel::CreateLights()
|
|||
{
|
||||
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)
|
||||
|
@ -480,7 +490,8 @@ void FLevel::CreateLights()
|
|||
thingLight->rgb.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
||||
thingLight->rgb.z = (lightcolor & 0xff) / 255.0f;
|
||||
thingLight->intensity = lightintensity;
|
||||
thingLight->falloff = 1.0f;
|
||||
thingLight->innerAngleCos = max(innerAngleCos, outerAngleCos);
|
||||
thingLight->outerAngleCos = outerAngleCos;
|
||||
thingLight->radius = lightdistance;
|
||||
thingLight->height = thing->height;
|
||||
thingLight->bCeiling = false;
|
||||
|
|
Loading…
Reference in a new issue