From 17698467d7b9055bc83ee7d007125df28a463434 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Dec 2016 12:58:45 +0100 Subject: [PATCH 1/3] - made application of dynamic lights to additively blended surfaces a MAPINFO option. In most cases this is not wanted but sometimes this can be used to good effect so it should be there as an option. --- src/gl/data/gl_data.cpp | 26 ++++++++++++++++++++++++-- src/gl/data/gl_data.h | 10 ++++++---- src/gl/renderer/gl_lightdata.cpp | 1 + src/gl/scene/gl_flats.cpp | 2 +- src/gl/scene/gl_walls_draw.cpp | 2 +- src/gl/scene/gl_weapon.cpp | 2 -- 6 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/gl/data/gl_data.cpp b/src/gl/data/gl_data.cpp index ad9c824bbd..47ad63e99a 100644 --- a/src/gl/data/gl_data.cpp +++ b/src/gl/data/gl_data.cpp @@ -57,6 +57,7 @@ long gl_frameCount; EXTERN_CVAR(Int, gl_lightmode) EXTERN_CVAR(Bool, gl_brightfog) +EXTERN_CVAR(Bool, gl_lightadditivesurfaces) CUSTOM_CVAR(Float, maxviewpitch, 90.f, CVAR_ARCHIVE|CVAR_SERVERINFO) { @@ -203,6 +204,7 @@ struct FGLROptions : public FOptionalMapinfoData skyrotatevector = FVector3(0,0,1); skyrotatevector2 = FVector3(0,0,1); pixelstretch = 1.2f; + lightadditivesurfaces = false; } virtual FOptionalMapinfoData *Clone() const { @@ -217,6 +219,7 @@ struct FGLROptions : public FOptionalMapinfoData newopt->skyrotatevector = skyrotatevector; newopt->skyrotatevector2 = skyrotatevector2; newopt->pixelstretch = pixelstretch; + newopt->lightadditivesurfaces = lightadditivesurfaces; return newopt; } int fogdensity; @@ -224,8 +227,9 @@ struct FGLROptions : public FOptionalMapinfoData int skyfog; int lightmode; int brightfog; - SBYTE nocoloredspritelighting; - SBYTE notexturefill; + int8_t lightadditivesurfaces; + int8_t nocoloredspritelighting; + int8_t notexturefill; FVector3 skyrotatevector; FVector3 skyrotatevector2; float pixelstretch; @@ -299,6 +303,20 @@ DEFINE_MAP_OPTION(notexturefill, false) } } +DEFINE_MAP_OPTION(lightadditivesurfaces, false) +{ + FGLROptions *opt = info->GetOptData("gl_renderer"); + if (parse.CheckAssign()) + { + parse.sc.MustGetNumber(); + opt->lightadditivesurfaces = !!parse.sc.Number; + } + else + { + opt->lightadditivesurfaces = true; + } +} + DEFINE_MAP_OPTION(skyrotate, false) { FGLROptions *opt = info->GetOptData("gl_renderer"); @@ -353,6 +371,7 @@ void InitGLRMapinfoData() { gl_SetFogParams(opt->fogdensity, level.info->outsidefog, opt->outsidefogdensity, opt->skyfog); glset.map_lightmode = opt->lightmode; + glset.map_lightadditivesurfaces = opt->lightadditivesurfaces; glset.map_brightfog = opt->brightfog; glset.map_nocoloredspritelighting = opt->nocoloredspritelighting; glset.map_notexturefill = opt->notexturefill; @@ -364,6 +383,7 @@ void InitGLRMapinfoData() { gl_SetFogParams(0, level.info->outsidefog, 0, 0); glset.map_lightmode = -1; + glset.map_lightadditivesurfaces = -1; glset.map_brightfog = -1; glset.map_nocoloredspritelighting = -1; glset.map_notexturefill = -1; @@ -380,6 +400,8 @@ void InitGLRMapinfoData() else glset.notexturefill = !!glset.map_notexturefill; if (glset.map_brightfog == -1) glset.brightfog = gl_brightfog; else glset.brightfog = !!glset.map_brightfog; + if (glset.map_lightadditivesurfaces == -1) glset.brightfog = gl_brightfog; + else glset.lightadditivesurfaces = !!glset.map_lightadditivesurfaces; } CCMD(gl_resetmap) diff --git a/src/gl/data/gl_data.h b/src/gl/data/gl_data.h index f1bc27ee4d..d6f789863c 100644 --- a/src/gl/data/gl_data.h +++ b/src/gl/data/gl_data.h @@ -12,11 +12,13 @@ struct GLRenderSettings bool nocoloredspritelighting; bool notexturefill; bool brightfog; + bool lightadditivesurfaces; - SBYTE map_lightmode; - SBYTE map_nocoloredspritelighting; - SBYTE map_notexturefill; - SBYTE map_brightfog; + int8_t map_lightmode; + int8_t map_nocoloredspritelighting; + int8_t map_notexturefill; + int8_t map_brightfog; + int8_t map_lightadditivesurfaces; FVector3 skyrotatevector; FVector3 skyrotatevector2; diff --git a/src/gl/renderer/gl_lightdata.cpp b/src/gl/renderer/gl_lightdata.cpp index 288af5c088..37f0a2e85b 100644 --- a/src/gl/renderer/gl_lightdata.cpp +++ b/src/gl/renderer/gl_lightdata.cpp @@ -63,6 +63,7 @@ CUSTOM_CVAR(Bool, gl_enhanced_nightvision, true, CVAR_ARCHIVE|CVAR_NOINITCALL) } } CVAR(Bool, gl_brightfog, false, CVAR_ARCHIVE); +CVAR(Bool, lightadditivesurfaces, false, CVAR_ARCHIVE); diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index c41e7664f9..bc47e448b6 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -109,7 +109,7 @@ void GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, int *dli) { Plane p; - if (renderstyle == STYLE_Add) return; // no lights on additively blended surfaces. + if (renderstyle == STYLE_Add && !glset.lightadditivesurfaces) return; // no lights on additively blended surfaces. if (dli != NULL && *dli != -1) { diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index dbc43fd22b..d392439e75 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -56,7 +56,7 @@ FDynLightData lightdata; void GLWall::SetupLights() { - if (RenderStyle == STYLE_Add) return; // no lights on additively blended surfaces. + if (RenderStyle == STYLE_Add && !glset.lightadditivesurfaces) return; // no lights on additively blended surfaces. // check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.) switch (type) diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index a2a12f947d..7662c78768 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -188,8 +188,6 @@ static bool isBright(DPSprite *psp) // //========================================================================== -EXTERN_CVAR(Bool, gl_brightfog) - void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) { bool brightflash = false; From c115c0a5b2dd99a8013c95061f283ee5a5d9beb9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Dec 2016 18:35:34 +0100 Subject: [PATCH 2/3] - fixed: Random flicker lights must set up their size on the first tic they are run. If not they will keep the radius of the previous effect which may be too large. --- src/gl/dynlights/a_dynlight.cpp | 21 ++++++++++++--------- src/gl/dynlights/gl_dynlight.cpp | 13 +++++++++++-- src/gl/dynlights/gl_dynlight.h | 7 +------ 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/gl/dynlights/a_dynlight.cpp b/src/gl/dynlights/a_dynlight.cpp index 0e52eedd8a..84e1d9ab1b 100644 --- a/src/gl/dynlights/a_dynlight.cpp +++ b/src/gl/dynlights/a_dynlight.cpp @@ -67,6 +67,7 @@ #include "templates.h" #include "doomdata.h" #include "r_utility.h" +#include "p_local.h" #include "portal.h" #include "doomstat.h" #include "serializer.h" @@ -192,6 +193,7 @@ void ADynamicLight::BeginPlay() m_Radius[0] = args[LIGHT_INTENSITY]; m_Radius[1] = args[LIGHT_SECONDARY_INTENSITY]; + specialf1 = DAngle(double(SpawnAngle)).Normalized360().Degrees; visibletoplayer = true; } @@ -228,7 +230,7 @@ void ADynamicLight::Activate(AActor *activator) if (lighttype == PulseLight) { - float pulseTime = Angles.Yaw.Degrees / TICRATE; + float pulseTime = specialf1 / TICRATE; m_lastUpdate = level.maptime; m_cycler.SetParams(float(m_Radius[1]), float(m_Radius[0]), pulseTime); @@ -293,7 +295,7 @@ void ADynamicLight::Tick() case FlickerLight: { BYTE rnd = randLight(); - float pct = Angles.Yaw.Degrees / 360.f; + float pct = specialf1 / 360.f; m_currentRadius = float(m_Radius[rnd >= pct * 255]); break; @@ -304,12 +306,13 @@ void ADynamicLight::Tick() int flickerRange = m_Radius[1] - m_Radius[0]; float amt = randLight() / 255.f; - m_tickCount++; - - if (m_tickCount > Angles.Yaw.Degrees) + if (m_tickCount > specialf1) + { + m_tickCount = 0; + } + if (m_tickCount++ == 0 || m_currentRadius > m_Radius[1]) { m_currentRadius = float(m_Radius[0] + (amt * flickerRange)); - m_tickCount = 0; } break; } @@ -319,7 +322,7 @@ void ADynamicLight::Tick() case ColorFlickerLight: { BYTE rnd = randLight(); - float pct = Angles.Yaw.Degrees/360.f; + float pct = specialf1/360.f; m_currentRadius = m_Radius[rnd >= pct * 255]; break; @@ -332,7 +335,7 @@ void ADynamicLight::Tick() m_tickCount++; - if (m_tickCount > Angles.Yaw.Degrees) + if (m_tickCount > specialf1) { m_currentRadius = m_Radius[0] + (amt * flickerRange); m_tickCount = 0; @@ -359,7 +362,6 @@ void ADynamicLight::Tick() m_currentRadius = float(m_Radius[0]); break; } - UpdateLocation(); } @@ -416,6 +418,7 @@ void ADynamicLight::UpdateLocation() intensity = m_currentRadius; } radius = intensity * 2.0f; + assert(radius >= m_currentRadius * 2); if (X() != oldx || Y() != oldy || radius != oldradius) { diff --git a/src/gl/dynlights/gl_dynlight.cpp b/src/gl/dynlights/gl_dynlight.cpp index 40008e3ad5..63ddfee605 100644 --- a/src/gl/dynlights/gl_dynlight.cpp +++ b/src/gl/dynlights/gl_dynlight.cpp @@ -164,7 +164,7 @@ FLightDefaults::FLightDefaults(FName name, ELightType type) void FLightDefaults::ApplyProperties(ADynamicLight * light) const { light->lighttype = m_type; - light->Angles.Yaw.Degrees = m_Param; + light->specialf1 = m_Param; light->SetOffset(m_Pos); light->halo = m_halo; for (int a = 0; a < 3; a++) light->args[a] = clamp((int)(m_Args[a]), 0, 255); @@ -174,6 +174,7 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const if (m_subtractive) light->flags4 |= MF4_SUBTRACTIVE; if (m_additive) light->flags4 |= MF4_ADDITIVE; if (m_dontlightself) light->flags4 |= MF4_DONTLIGHTSELF; + light->m_tickCount = 0; } @@ -431,6 +432,14 @@ void gl_ParsePulseLight(FScanner &sc) sc.ScriptError("Unknown tag: %s\n", sc.String); } } + if (defaults->GetArg(LIGHT_INTENSITY) > defaults->GetArg(LIGHT_SECONDARY_INTENSITY)) + { + auto i = defaults->GetArg(LIGHT_INTENSITY); + auto j = defaults->GetArg(LIGHT_SECONDARY_INTENSITY); + defaults->SetArg(LIGHT_INTENSITY, j); + defaults->SetArg(LIGHT_SECONDARY_INTENSITY, i); + } + gl_AddLightDefaults(defaults); } else @@ -1082,7 +1091,7 @@ void gl_AttachLight(AActor *actor, unsigned int count, const FLightDefaults *lig light->target = actor; light->owned = true; light->ObjectFlags |= OF_Transient; - light->flags4 |= MF4_ATTENUATE; + //light->flags4 |= MF4_ATTENUATE; actor->dynamiclights.Push(light); } light->flags2&=~MF2_DORMANT; diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h index c51e0c79d8..e8448890bc 100644 --- a/src/gl/dynlights/gl_dynlight.h +++ b/src/gl/dynlights/gl_dynlight.h @@ -128,12 +128,12 @@ private: protected: DVector3 m_off; float m_currentRadius; - int m_tickCount; unsigned int m_lastUpdate; FCycler m_cycler; subsector_t * subsector; public: + int m_tickCount; int m_Radius[2]; BYTE lightflags; BYTE lighttype; @@ -143,11 +143,6 @@ public: bool visibletoplayer; int bufferindex; - // intermediate texture coordinate data - // this is stored in the light object to avoid recalculating it - // several times during rendering of a flat - Vector nearPt, up, right; - float scale; }; From a3ae05299b6b72f11e37f69c4972aaf7b81cd102 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Dec 2016 19:17:02 +0100 Subject: [PATCH 3/3] - fixed: glPolygonOffset was not called for flat sprites. --- src/gl/scene/gl_sprite.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index e9748fba61..f79549a39a 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -142,6 +142,9 @@ void GLSprite::CalculateVertices(FVector3 *v) v[1] = mat * FVector3(x1, z, y2); v[2] = mat * FVector3(x2, z, y1); v[3] = mat * FVector3(x1, z, y1); + + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -128.0f); return; } @@ -445,6 +448,11 @@ void GLSprite::Draw(int pass) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.BlendEquation(GL_FUNC_ADD); gl_RenderState.SetTextureMode(TM_MODULATE); + if (actor != nullptr && (actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE) + { + glPolygonOffset(0.0f, 0.0f); + glDisable(GL_POLYGON_OFFSET_FILL); + } } else if (modelframe == nullptr) {