diff --git a/src/playsim/a_dynlight.h b/src/playsim/a_dynlight.h index 586c9c799..9214d8ff4 100644 --- a/src/playsim/a_dynlight.h +++ b/src/playsim/a_dynlight.h @@ -42,7 +42,8 @@ enum LightFlag LF_DONTLIGHTACTORS = 32, LF_SPOT = 64, LF_DONTLIGHTOTHERS = 128, - LF_DONTLIGHTMAP = 256 + LF_DONTLIGHTMAP = 256, + LF_TRACE = 512 }; typedef TFlags LightFlags; @@ -76,6 +77,7 @@ public: void SetDontLightActors(bool on) { if (on) m_lightFlags |= LF_DONTLIGHTACTORS; else m_lightFlags &= ~LF_DONTLIGHTACTORS; } void SetDontLightOthers(bool on) { if (on) m_lightFlags |= LF_DONTLIGHTOTHERS; else m_lightFlags &= ~LF_DONTLIGHTOTHERS; } void SetDontLightMap(bool on) { if (on) m_lightFlags |= LF_DONTLIGHTMAP; else m_lightFlags &= ~LF_DONTLIGHTMAP; } + void SetTrace(bool on) { if (on) m_lightFlags |= LF_TRACE; else m_lightFlags &= ~LF_TRACE; } void SetNoShadowmap(bool on) { if (on) m_lightFlags |= LF_NOSHADOWMAP; else m_lightFlags &= ~LF_NOSHADOWMAP; } void SetSpot(bool spot) { if (spot) m_lightFlags |= LF_SPOT; else m_lightFlags &= ~LF_SPOT; } void SetSpotInnerAngle(double angle) { m_spotInnerAngle = angle; } @@ -230,6 +232,7 @@ struct FDynamicLight bool IsAdditive() const { return !!((*pLightFlags) & LF_ADDITIVE); } bool IsSpot() const { return !!((*pLightFlags) & LF_SPOT); } bool IsAttenuated() const { return !!((*pLightFlags) & LF_ATTENUATE); } + bool Trace() const { return !!((*pLightFlags) & (LF_TRACE)); } bool DontShadowmap() const { return !!((*pLightFlags) & LF_NOSHADOWMAP); } bool DontLightSelf() const { return !!((*pLightFlags) & (LF_DONTLIGHTSELF|LF_DONTLIGHTACTORS)); } // dontlightactors implies dontlightself. bool DontLightActors() const { return !!((*pLightFlags) & LF_DONTLIGHTACTORS); } diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp index 4218c3f0e..aac9c06df 100644 --- a/src/r_data/gldefs.cpp +++ b/src/r_data/gldefs.cpp @@ -191,6 +191,7 @@ static const char *LightTags[]= "noshadowmap", "dontlightothers", "dontlightmap", + "trace", nullptr }; @@ -217,6 +218,7 @@ enum { LIGHTTAG_NOSHADOWMAP, LIGHTTAG_DONTLIGHTOTHERS, LIGHTTAG_DONTLIGHTMAP, + LIGHTTAG_TRACE, }; //========================================================================== @@ -523,6 +525,9 @@ class GLDefsParser case LIGHTTAG_DONTLIGHTMAP: defaults->SetDontLightMap(ParseInt(sc) != 0); break; + case LIGHTTAG_TRACE: + defaults->SetTrace(ParseInt(sc) != 0); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -625,6 +630,9 @@ class GLDefsParser case LIGHTTAG_DONTLIGHTMAP: defaults->SetDontLightMap(ParseInt(sc) != 0); break; + case LIGHTTAG_TRACE: + defaults->SetTrace(ParseInt(sc) != 0); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -730,6 +738,9 @@ class GLDefsParser case LIGHTTAG_DONTLIGHTMAP: defaults->SetDontLightMap(ParseInt(sc) != 0); break; + case LIGHTTAG_TRACE: + defaults->SetTrace(ParseInt(sc) != 0); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -834,6 +845,9 @@ class GLDefsParser case LIGHTTAG_DONTLIGHTMAP: defaults->SetDontLightMap(ParseInt(sc) != 0); break; + case LIGHTTAG_TRACE: + defaults->SetTrace(ParseInt(sc) != 0); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -935,6 +949,9 @@ class GLDefsParser case LIGHTTAG_DONTLIGHTMAP: defaults->SetDontLightMap(ParseInt(sc) != 0); break; + case LIGHTTAG_TRACE: + defaults->SetTrace(ParseInt(sc) != 0); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index f9998398a..64f98f650 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -101,6 +101,16 @@ LightProbe* FindLightProbe(FLevelLocals* level, float x, float y, float z) return foundprobe; } +static bool TraceLightVisbility(FLightNode* node, const FVector3& L, float dist) +{ + FDynamicLight* light = node->lightsource; + if (!light->Trace()) + return true; + + FTraceResults results; + return !Trace(light->Pos, light->Sector, DVector3(-L.X, -L.Y, -L.Z), dist, 0, ML_BLOCKING, nullptr, results); +} + //========================================================================== // // Sets a single light value from all dynamic lights affecting the specified location @@ -115,14 +125,6 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLig out[0] = out[1] = out[2] = 0.f; - LightProbe* probe = FindLightProbe(Level, x, y, z); - if (probe) - { - out[0] = probe->Red; - out[1] = probe->Green; - out[2] = probe->Blue; - } - // Go through both light lists while (node) { @@ -156,38 +158,43 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLig { dist = sqrtf(dist); // only calculate the square root if we really need it. - frac = 1.0f - (dist / radius); - - if (light->IsSpot()) - { + if (light->IsSpot() || light->Trace()) L *= -1.0f / dist; - DAngle negPitch = -*light->pPitch; - DAngle Angle = light->target->Angles.Yaw; - double xyLen = negPitch.Cos(); - double spotDirX = -Angle.Cos() * xyLen; - double spotDirY = -Angle.Sin() * xyLen; - double spotDirZ = -negPitch.Sin(); - double cosDir = L.X * spotDirX + L.Y * spotDirY + L.Z * spotDirZ; - frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir); - } - if (frac > 0 && (!light->shadowmapped || (light->GetRadius() > 0 && screen->mShadowMap.ShadowTest(light->Pos, { x, y, z })))) + if (TraceLightVisbility(node, L, dist)) { - lr = light->GetRed() / 255.0f; - lg = light->GetGreen() / 255.0f; - lb = light->GetBlue() / 255.0f; - if (light->IsSubtractive()) + frac = 1.0f - (dist / radius); + + if (light->IsSpot()) { - float bright = (float)FVector3(lr, lg, lb).Length(); - FVector3 lightColor(lr, lg, lb); - lr = (bright - lr) * -1; - lg = (bright - lg) * -1; - lb = (bright - lb) * -1; + DAngle negPitch = -*light->pPitch; + DAngle Angle = light->target->Angles.Yaw; + double xyLen = negPitch.Cos(); + double spotDirX = -Angle.Cos() * xyLen; + double spotDirY = -Angle.Sin() * xyLen; + double spotDirZ = -negPitch.Sin(); + double cosDir = L.X * spotDirX + L.Y * spotDirY + L.Z * spotDirZ; + frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir); } - out[0] += lr * frac; - out[1] += lg * frac; - out[2] += lb * frac; + if (frac > 0 && (!light->shadowmapped || (light->GetRadius() > 0 && screen->mShadowMap.ShadowTest(light->Pos, { x, y, z })))) + { + lr = light->GetRed() / 255.0f; + lg = light->GetGreen() / 255.0f; + lb = light->GetBlue() / 255.0f; + if (light->IsSubtractive()) + { + float bright = (float)FVector3(lr, lg, lb).Length(); + FVector3 lightColor(lr, lg, lb); + lr = (bright - lr) * -1; + lg = (bright - lg) * -1; + lb = (bright - lb) * -1; + } + + out[0] += lr * frac; + out[1] += lg * frac; + out[2] += lb * frac; + } } } } @@ -249,7 +256,16 @@ void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata) { if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector { - AddLightToList(modellightdata, group, light, true); + FVector3 L(dx, dy, dz); + float dist = sqrtf(distSquared); + if (light->Trace()) + L *= 1.0f / dist; + + if (TraceLightVisbility(node, L, dist)) + { + AddLightToList(modellightdata, group, light, true); + } + addedLights.Push(light); } } diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 3e44171db..5947f2f99 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -294,13 +294,6 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) } else { - if (actor && di->Level->LightProbes.Size() > 0) - { - LightProbe* probe = FindLightProbe(di->Level, actor->X(), actor->Y(), actor->Center()); - if (probe) - state.SetDynLight(probe->Red, probe->Green, probe->Blue); - } - FHWModelRenderer renderer(di, state, dynlightindex); RenderModel(&renderer, x, y, z, modelframe, actor, di->Viewpoint.TicFrac); state.SetVertexBuffer(screen->mVertexData); diff --git a/src/rendering/hwrenderer/scene/hw_weapon.cpp b/src/rendering/hwrenderer/scene/hw_weapon.cpp index 5125b41b9..579c0e3b2 100644 --- a/src/rendering/hwrenderer/scene/hw_weapon.cpp +++ b/src/rendering/hwrenderer/scene/hw_weapon.cpp @@ -646,13 +646,6 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area) { hw_GetDynModelLight(playermo, lightdata); hudsprite.lightindex = screen->mLights->UploadLights(lightdata); - LightProbe* probe = FindLightProbe(playermo->Level, playermo->X(), playermo->Y(), playermo->Center()); - if (probe) - { - hudsprite.dynrgb[0] = probe->Red; - hudsprite.dynrgb[1] = probe->Green; - hudsprite.dynrgb[2] = probe->Blue; - } } } diff --git a/wadsrc/static/mapinfo/common.txt b/wadsrc/static/mapinfo/common.txt index 6982a5bce..a67e54722 100644 --- a/wadsrc/static/mapinfo/common.txt +++ b/wadsrc/static/mapinfo/common.txt @@ -137,8 +137,8 @@ DoomEdNums 9873 = SectorSpotLightAttenuated 9874 = SpotLightFlickerRandomAttenuated 9875 = None // ZDRay light probe - 9876 = None // ZDRay static point light - 9881 = None // ZDRay static spotlight + 9876 = PointLightTraceAttenuated // ZDRay static point light + 9881 = SpotLightTraceAttenuated // ZDRay static spotlight 9890 = None // ZDRayInfo 9982 = SecActEyesAboveC 9983 = SecActEyesBelowC diff --git a/wadsrc/static/zscript/actors/shared/dynlights.zs b/wadsrc/static/zscript/actors/shared/dynlights.zs index 8c5d0850d..132c78fd0 100644 --- a/wadsrc/static/zscript/actors/shared/dynlights.zs +++ b/wadsrc/static/zscript/actors/shared/dynlights.zs @@ -17,6 +17,7 @@ class DynamicLight : Actor flagdef spot: lightflags, 6; flagdef dontlightothers: lightflags, 7; flagdef dontlightmap: lightflags, 8; + flagdef trace: lightflags, 9; enum EArgs { @@ -40,6 +41,7 @@ class DynamicLight : Actor LF_SPOT = 64, LF_DONTLIGHTOTHERS = 128, LF_DONTLIGHTMAP = 256, + LF_TRACE = 512 }; enum ELightType @@ -440,6 +442,25 @@ class SpotLightFlickerRandomAttenuated : SpotLightFlickerRandom } } +class PointLightTraceAttenuated : PointLightAttenuated +{ + Default + { + +DYNAMICLIGHT.TRACE + +DYNAMICLIGHT.DONTLIGHTMAP + } +} + +class SpotLightTraceAttenuated : SpotLightAttenuated +{ + Default + { + +DYNAMICLIGHT.TRACE + +DYNAMICLIGHT.DONTLIGHTMAP + } +} + + class VavoomLight : DynamicLight { Default