mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-22 20:21:26 +00:00
- Add dynamic spot lights
This commit is contained in:
parent
4b044e30d7
commit
5f36b86013
7 changed files with 134 additions and 13 deletions
|
@ -114,6 +114,9 @@ DEFINE_CLASS_PROPERTY(type, S, DynamicLight)
|
|||
//==========================================================================
|
||||
IMPLEMENT_CLASS(ADynamicLight, false, false)
|
||||
|
||||
DEFINE_FIELD(ADynamicLight, SpotInnerAngle)
|
||||
DEFINE_FIELD(ADynamicLight, SpotOuterAngle)
|
||||
|
||||
static FRandom randLight;
|
||||
|
||||
//==========================================================================
|
||||
|
@ -134,7 +137,9 @@ void ADynamicLight::Serialize(FSerializer &arc)
|
|||
arc("lightflags", lightflags, def->lightflags)
|
||||
("lighttype", lighttype, def->lighttype)
|
||||
("tickcount", m_tickCount, def->m_tickCount)
|
||||
("currentradius", m_currentRadius, def->m_currentRadius);
|
||||
("currentradius", m_currentRadius, def->m_currentRadius)
|
||||
("spotinnerangle", SpotInnerAngle, def->SpotInnerAngle)
|
||||
("spotouterangle", SpotOuterAngle, def->SpotOuterAngle);
|
||||
|
||||
if (lighttype == PulseLight)
|
||||
arc("lastupdate", m_lastUpdate, def->m_lastUpdate)
|
||||
|
|
|
@ -28,7 +28,8 @@ enum LightFlag
|
|||
LF_DONTLIGHTSELF = 4,
|
||||
LF_ATTENUATE = 8,
|
||||
LF_NOSHADOWMAP = 16,
|
||||
LF_DONTLIGHTACTORS = 32
|
||||
LF_DONTLIGHTACTORS = 32,
|
||||
LF_SPOT = 64
|
||||
};
|
||||
|
||||
typedef TFlags<LightFlag> LightFlags;
|
||||
|
@ -42,7 +43,7 @@ enum ELightType
|
|||
FlickerLight,
|
||||
RandomFlickerLight,
|
||||
SectorLight,
|
||||
SpotLight,
|
||||
DummyLight,
|
||||
ColorPulseLight,
|
||||
ColorFlickerLight,
|
||||
RandomColorFlickerLight
|
||||
|
@ -100,6 +101,7 @@ public:
|
|||
bool IsActive() const { return !(flags2&MF2_DORMANT); }
|
||||
bool IsSubtractive() { return !!(lightflags & LF_SUBTRACTIVE); }
|
||||
bool IsAdditive() { return !!(lightflags & LF_ADDITIVE); }
|
||||
bool IsSpot() { return !!(lightflags & LF_SPOT); }
|
||||
FState *targetState;
|
||||
FLightNode * touching_sides;
|
||||
FLightNode * touching_subsectors;
|
||||
|
@ -127,6 +129,7 @@ public:
|
|||
bool shadowmapped;
|
||||
int bufferindex;
|
||||
LightFlags lightflags;
|
||||
|
||||
DAngle SpotInnerAngle = 10.0;
|
||||
DAngle SpotOuterAngle = 25.0;
|
||||
|
||||
};
|
||||
|
|
|
@ -128,6 +128,9 @@ public:
|
|||
void SetAttenuate(bool on) { m_attenuate = on; }
|
||||
void SetHalo(bool halo) { m_halo = halo; }
|
||||
void SetDontLightActors(bool on) { m_dontlightactors = on; }
|
||||
void SetSpot(bool spot) { m_spot = spot; }
|
||||
void SetSpotInnerAngle(double angle) { m_spotInnerAngle = angle; }
|
||||
void SetSpotOuterAngle(double angle) { m_spotOuterAngle = angle; }
|
||||
|
||||
void OrderIntensities()
|
||||
{
|
||||
|
@ -151,6 +154,9 @@ protected:
|
|||
bool m_dontlightself = false;
|
||||
bool m_dontlightactors = false;
|
||||
bool m_swapped = false;
|
||||
bool m_spot = false;
|
||||
double m_spotInnerAngle = 10.0;
|
||||
double m_spotOuterAngle = 25.0;
|
||||
};
|
||||
|
||||
TDeletingArray<FLightDefaults *> LightDefaults;
|
||||
|
@ -183,6 +189,10 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const
|
|||
if (m_additive) light->lightflags |= LF_ADDITIVE;
|
||||
if (m_dontlightself) light->lightflags |= LF_DONTLIGHTSELF;
|
||||
if (m_dontlightactors) light->lightflags |= LF_DONTLIGHTACTORS;
|
||||
if (m_spot)
|
||||
light->lightflags |= LF_SPOT;
|
||||
light->SpotInnerAngle = m_spotInnerAngle;
|
||||
light->SpotOuterAngle = m_spotOuterAngle;
|
||||
light->m_tickCount = 0;
|
||||
if (m_type == PulseLight)
|
||||
{
|
||||
|
@ -233,7 +243,8 @@ static const char *LightTags[]=
|
|||
"dontlightself",
|
||||
"attenuate",
|
||||
"dontlightactors",
|
||||
NULL
|
||||
"spot",
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
||||
|
@ -255,6 +266,7 @@ enum {
|
|||
LIGHTTAG_DONTLIGHTSELF,
|
||||
LIGHTTAG_ATTENUATE,
|
||||
LIGHTTAG_DONTLIGHTACTORS,
|
||||
LIGHTTAG_SPOT
|
||||
};
|
||||
|
||||
|
||||
|
@ -395,6 +407,15 @@ static void ParsePointLight(FScanner &sc)
|
|||
case LIGHTTAG_DONTLIGHTACTORS:
|
||||
defaults->SetDontLightActors(ParseInt(sc) != 0);
|
||||
break;
|
||||
case LIGHTTAG_SPOT:
|
||||
{
|
||||
float innerAngle = ParseFloat(sc);
|
||||
float outerAngle = ParseFloat(sc);
|
||||
defaults->SetSpot(true);
|
||||
defaults->SetSpotInnerAngle(innerAngle);
|
||||
defaults->SetSpotOuterAngle(outerAngle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
||||
}
|
||||
|
@ -480,6 +501,15 @@ static void ParsePulseLight(FScanner &sc)
|
|||
case LIGHTTAG_DONTLIGHTACTORS:
|
||||
defaults->SetDontLightActors(ParseInt(sc) != 0);
|
||||
break;
|
||||
case LIGHTTAG_SPOT:
|
||||
{
|
||||
float innerAngle = ParseFloat(sc);
|
||||
float outerAngle = ParseFloat(sc);
|
||||
defaults->SetSpot(true);
|
||||
defaults->SetSpotInnerAngle(innerAngle);
|
||||
defaults->SetSpotOuterAngle(outerAngle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
||||
}
|
||||
|
@ -567,6 +597,15 @@ void ParseFlickerLight(FScanner &sc)
|
|||
case LIGHTTAG_DONTLIGHTACTORS:
|
||||
defaults->SetDontLightActors(ParseInt(sc) != 0);
|
||||
break;
|
||||
case LIGHTTAG_SPOT:
|
||||
{
|
||||
float innerAngle = ParseFloat(sc);
|
||||
float outerAngle = ParseFloat(sc);
|
||||
defaults->SetSpot(true);
|
||||
defaults->SetSpotInnerAngle(innerAngle);
|
||||
defaults->SetSpotOuterAngle(outerAngle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
||||
}
|
||||
|
@ -653,6 +692,15 @@ void ParseFlickerLight2(FScanner &sc)
|
|||
case LIGHTTAG_DONTLIGHTACTORS:
|
||||
defaults->SetDontLightActors(ParseInt(sc) != 0);
|
||||
break;
|
||||
case LIGHTTAG_SPOT:
|
||||
{
|
||||
float innerAngle = ParseFloat(sc);
|
||||
float outerAngle = ParseFloat(sc);
|
||||
defaults->SetSpot(true);
|
||||
defaults->SetSpotInnerAngle(innerAngle);
|
||||
defaults->SetSpotOuterAngle(outerAngle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
||||
}
|
||||
|
@ -736,6 +784,15 @@ static void ParseSectorLight(FScanner &sc)
|
|||
case LIGHTTAG_DONTLIGHTACTORS:
|
||||
defaults->SetDontLightActors(ParseInt(sc) != 0);
|
||||
break;
|
||||
case LIGHTTAG_SPOT:
|
||||
{
|
||||
float innerAngle = ParseFloat(sc);
|
||||
float outerAngle = ParseFloat(sc);
|
||||
defaults->SetSpot(true);
|
||||
defaults->SetSpotInnerAngle(innerAngle);
|
||||
defaults->SetSpotOuterAngle(outerAngle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
||||
}
|
||||
|
|
|
@ -128,7 +128,26 @@ void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata)
|
|||
|
||||
if (attenuate) shadowIndex = -shadowIndex;
|
||||
|
||||
float *data = &ldata.arrays[i][ldata.arrays[i].Reserve(8)];
|
||||
float lightType = 0.0f;
|
||||
float spotInnerAngle = 0.0f;
|
||||
float spotOuterAngle = 0.0f;
|
||||
float spotDirX = 0.0f;
|
||||
float spotDirY = 0.0f;
|
||||
float spotDirZ = 0.0f;
|
||||
if (light->IsSpot())
|
||||
{
|
||||
lightType = 1.0f;
|
||||
spotInnerAngle = light->SpotInnerAngle.Cos();
|
||||
spotOuterAngle = light->SpotOuterAngle.Cos();
|
||||
|
||||
DAngle negPitch = -light->Angles.Pitch;
|
||||
float xyLen = negPitch.Cos();
|
||||
spotDirX = light->Angles.Yaw.Cos() * xyLen;
|
||||
spotDirY = light->Angles.Yaw.Sin() * xyLen;
|
||||
spotDirZ = negPitch.Sin();
|
||||
}
|
||||
|
||||
float *data = &ldata.arrays[i][ldata.arrays[i].Reserve(16)];
|
||||
data[0] = pos.X;
|
||||
data[1] = pos.Z;
|
||||
data[2] = pos.Y;
|
||||
|
@ -137,5 +156,13 @@ void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata)
|
|||
data[5] = g;
|
||||
data[6] = b;
|
||||
data[7] = shadowIndex;
|
||||
data[8] = spotDirX;
|
||||
data[9] = spotDirY;
|
||||
data[10] = spotDirZ;
|
||||
data[11] = lightType;
|
||||
data[12] = spotInnerAngle;
|
||||
data[13] = spotOuterAngle;
|
||||
data[14] = 0.0f; // unused
|
||||
data[15] = 0.0f; // unused
|
||||
}
|
||||
|
||||
|
|
|
@ -494,6 +494,7 @@ static FFlagDef DynLightFlagDefs[] =
|
|||
DEFINE_FLAG(LF, ATTENUATE, ADynamicLight, lightflags),
|
||||
DEFINE_FLAG(LF, NOSHADOWMAP, ADynamicLight, lightflags),
|
||||
DEFINE_FLAG(LF, DONTLIGHTACTORS, ADynamicLight, lightflags),
|
||||
DEFINE_FLAG(LF, SPOT, ADynamicLight, lightflags),
|
||||
};
|
||||
|
||||
static FFlagDef PowerSpeedFlagDefs[] =
|
||||
|
|
|
@ -278,6 +278,13 @@ float pointLightAttenuation(vec4 lightpos, float lightcolorA)
|
|||
}
|
||||
}
|
||||
|
||||
float spotLightAttenuation(vec4 lightpos, vec3 spotdir, float lightCosInnerAngle, float lightCosOuterAngle)
|
||||
{
|
||||
vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz);
|
||||
float cosDir = dot(lightDirection, spotdir);
|
||||
return smoothstep(lightCosOuterAngle, lightCosInnerAngle, cosDir);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Calculate light
|
||||
|
@ -348,23 +355,33 @@ vec4 getLightColor(float fogdist, float fogfactor)
|
|||
//
|
||||
// modulated lights
|
||||
//
|
||||
for(int i=lightRange.x; i<lightRange.y; i+=2)
|
||||
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
lightcolor.rgb *= pointLightAttenuation(lightpos, lightcolor.a);
|
||||
float attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
lightcolor.rgb *= attenuation;
|
||||
dynlight.rgb += lightcolor.rgb;
|
||||
}
|
||||
//
|
||||
// subtractive lights
|
||||
//
|
||||
for(int i=lightRange.y; i<lightRange.z; i+=2)
|
||||
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
lightcolor.rgb *= pointLightAttenuation(lightpos, lightcolor.a);
|
||||
float attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
lightcolor.rgb *= attenuation;
|
||||
dynlight.rgb -= lightcolor.rgb;
|
||||
}
|
||||
}
|
||||
|
@ -467,12 +484,17 @@ void main()
|
|||
//
|
||||
// additive lights - these can be done after the alpha test.
|
||||
//
|
||||
for(int i=lightRange.z; i<lightRange.w; i+=2)
|
||||
for(int i=lightRange.z; i<lightRange.w; i+=4)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
lightcolor.rgb *= pointLightAttenuation(lightpos, lightcolor.a);
|
||||
float attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
lightcolor.rgb *= attenuation;
|
||||
addlight.rgb += lightcolor.rgb;
|
||||
}
|
||||
frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
class DynamicLight : Actor native
|
||||
{
|
||||
native double SpotInnerAngle;
|
||||
native double SpotOuterAngle;
|
||||
|
||||
property SpotInnerAngle: SpotInnerAngle;
|
||||
property SpotOuterAngle: SpotOuterAngle;
|
||||
|
||||
enum EArgs
|
||||
{
|
||||
LIGHT_RED = 0,
|
||||
|
@ -17,7 +23,7 @@ class DynamicLight : Actor native
|
|||
FlickerLight,
|
||||
RandomFlickerLight,
|
||||
SectorLight,
|
||||
SpotLight,
|
||||
DummyLight,
|
||||
ColorPulseLight,
|
||||
ColorFlickerLight,
|
||||
RandomColorFlickerLight
|
||||
|
|
Loading…
Reference in a new issue