diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 079ec15c6..b0f666e1e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -821,7 +821,6 @@ set( FASTMATH_SOURCES textures/hires/xbr/xbrz.cpp textures/hires/xbr/xbrz_old.cpp gl/scene/gl_drawinfo.cpp - gl/scene/gl_sprite.cpp gl/scene/gl_skydome.cpp gl/scene/gl_weapon.cpp gl/scene/gl_scene.cpp diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index 7e2609b4e..1125208b5 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -41,6 +41,7 @@ #include "gl/scene/gl_portal.h" #include "gl/renderer/gl_renderstate.h" #include "gl/dynlights/gl_lightbuffer.h" +#include "gl/models/gl_models.h" class FDrawInfoList { @@ -90,13 +91,13 @@ void FDrawInfo::DoDrawSorted(HWDrawList *dl, SortNode * head) DoDrawSorted(dl, head->left); gl_RenderState.SetClipSplit(clipsplit); } - dl->DoDraw(this, gl_RenderState, true, GLPASS_TRANSLUCENT, head->itemindex, true); + dl->DoDraw(this, gl_RenderState, true, head->itemindex); if (head->equal) { SortNode * ehead=head->equal; while (ehead) { - dl->DoDraw(this, gl_RenderState, true, GLPASS_TRANSLUCENT, ehead->itemindex, true); + dl->DoDraw(this, gl_RenderState, true, ehead->itemindex); ehead=ehead->equal; } } @@ -298,6 +299,12 @@ void FDrawInfo::DrawIndexed(EDrawType dt, FRenderState &state, int index, int co drawcalls.Unclock(); } +void FDrawInfo::DrawModel(GLSprite *spr, FRenderState &state) +{ + FGLModelRenderer renderer(this, spr->dynlightindex); + renderer.RenderModel(spr->x, spr->y, spr->z, spr->modelframe, spr->actor, Viewpoint.TicFrac); +} + void FDrawInfo::SetDepthMask(bool on) { glDepthMask(on); @@ -357,3 +364,26 @@ void FDrawInfo::AddFlat(GLFlat *flat, bool fog) *newflat = *flat; } + +//========================================================================== +// +// +// +//========================================================================== +void FDrawInfo::AddSprite(GLSprite *sprite, bool translucent) +{ + int list; + // [BB] Allow models to be drawn in the GLDL_TRANSLUCENT pass. + if (translucent || sprite->actor == nullptr || (!sprite->modelframe && (sprite->actor->renderflags & RF_SPRITETYPEMASK) != RF_WALLSPRITE)) + { + list = GLDL_TRANSLUCENT; + } + else + { + list = GLDL_MODELS; + } + + auto newsprt = drawlists[list].NewSprite(); + *newsprt = *sprite; +} + diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 4586ed3bb..dc306221c 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -26,11 +26,6 @@ enum DrawListType GLDL_TYPES, }; -enum Drawpasses -{ - GLPASS_ALL, // Main pass with dynamic lights - GLPASS_TRANSLUCENT, // Draws translucent objects -}; struct FDrawInfo : public HWDrawInfo { @@ -52,14 +47,14 @@ struct FDrawInfo : public HWDrawInfo void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override; void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override; + void DrawModel(GLSprite *spr, FRenderState &state) override; + void SetDepthMask(bool on) override; void SetDepthFunc(int func) override; void EnableDrawBufferAttachments(bool on) override; void StartScene(); - // Sprite drawer - void DrawSprite(GLSprite *sprite, int pass); void DrawPSprite(HUDSprite *huds); void DrawPlayerSprites(bool hudModelStep); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 71893795c..34319f8b1 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -168,8 +168,6 @@ void FDrawInfo::RenderScene(int recursion) gl_RenderState.AlphaFunc(Alpha_GEqual, 0.f); glDisable(GL_POLYGON_OFFSET_FILL); - int pass = GLPASS_ALL; - gl_RenderState.EnableTexture(gl_texture); gl_RenderState.EnableBrightmap(true); drawlists[GLDL_PLAINWALLS].DrawWalls(this, gl_RenderState, false); @@ -189,7 +187,7 @@ void FDrawInfo::RenderScene(int recursion) gl_RenderState.ClearDepthBias(); } - drawlists[GLDL_MODELS].Draw(this, gl_RenderState, false, pass); + drawlists[GLDL_MODELS].Draw(this, gl_RenderState, false); gl_RenderState.SetRenderStyle(STYLE_Translucent); @@ -215,7 +213,7 @@ void FDrawInfo::RenderTranslucent() gl_RenderState.SetRenderStyle(STYLE_Translucent); gl_RenderState.EnableBrightmap(true); - drawlists[GLDL_TRANSLUCENTBORDER].Draw(this, gl_RenderState, true, GLPASS_TRANSLUCENT); + drawlists[GLDL_TRANSLUCENTBORDER].Draw(this, gl_RenderState, true); glDepthMask(false); DrawSorted(GLDL_TRANSLUCENT); gl_RenderState.EnableBrightmap(false); diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp deleted file mode 100644 index 94304c535..000000000 --- a/src/gl/scene/gl_sprite.cpp +++ /dev/null @@ -1,316 +0,0 @@ -// -//--------------------------------------------------------------------------- -// -// Copyright(C) 2002-2016 Christoph Oelckers -// All rights reserved. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//-------------------------------------------------------------------------- -// -/* -** gl_sprite.cpp -** Sprite/Particle rendering -** -*/ - -#include "gl_load/gl_system.h" -#include "p_local.h" -#include "p_effect.h" -#include "g_level.h" -#include "doomstat.h" -#include "r_defs.h" -#include "r_sky.h" -#include "r_utility.h" -#include "a_pickups.h" -#include "d_player.h" -#include "g_levellocals.h" -#include "events.h" -#include "actorinlines.h" -#include "r_data/r_vanillatrans.h" - -#include "gl_load/gl_interface.h" -#include "hwrenderer/utility/hw_cvars.h" -#include "hwrenderer/scene/hw_drawstructs.h" -#include "gl/renderer/gl_renderstate.h" -#include "gl/renderer/gl_renderer.h" -#include "gl/scene/gl_drawinfo.h" -#include "gl/models/gl_models.h" -#include "gl/dynlights/gl_lightbuffer.h" -#include "hwrenderer/utility/hw_lighting.h" - -extern uint32_t r_renderercaps; - -//========================================================================== -// -// -// -//========================================================================== - -void FDrawInfo::DrawSprite(GLSprite *sprite, int pass) -{ - auto RenderStyle = sprite->RenderStyle; - - bool additivefog = false; - bool foglayer = false; - int rel = sprite->fullbright? 0 : getExtraLight(); - auto &vp = Viewpoint; - - if (pass==GLPASS_TRANSLUCENT) - { - // The translucent pass requires special setup for the various modes. - - // for special render styles brightmaps would not look good - especially for subtractive. - if (RenderStyle.BlendOp != STYLEOP_Add) - { - gl_RenderState.EnableBrightmap(false); - } - - // Optionally use STYLE_ColorBlend in place of STYLE_Add for fullbright items. - if (RenderStyle == LegacyRenderStyles[STYLE_Add] && sprite->trans > 1.f - FLT_EPSILON && - gl_usecolorblending && !isFullbrightScene() && sprite->actor && - sprite->fullbright && sprite->gltexture && !sprite->gltexture->tex->GetTranslucency()) - { - RenderStyle = LegacyRenderStyles[STYLE_ColorBlend]; - } - - gl_RenderState.SetRenderStyle(RenderStyle); - gl_RenderState.SetTextureMode(RenderStyle); - - if (sprite->hw_styleflags == STYLEHW_NoAlphaTest) - { - gl_RenderState.AlphaFunc(Alpha_GEqual, 0.f); - } - else - { - gl_RenderState.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); - } - - if (RenderStyle.BlendOp == STYLEOP_Shadow) - { - float fuzzalpha=0.44f; - float minalpha=0.1f; - - // fog + fuzz don't work well without some fiddling with the alpha value! - if (!sprite->Colormap.FadeColor.isBlack()) - { - float dist=Dist2(vp.Pos.X, vp.Pos.Y, sprite->x, sprite->y); - int fogd = hw_GetFogDensity(sprite->lightlevel, sprite->Colormap.FadeColor, sprite->Colormap.FogDensity, sprite->Colormap.BlendFactor); - - // this value was determined by trial and error and is scale dependent! - float factor = 0.05f + exp(-fogd*dist / 62500.f); - fuzzalpha*=factor; - minalpha*=factor; - } - - gl_RenderState.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); - gl_RenderState.SetColor(0.2f,0.2f,0.2f,fuzzalpha, sprite->Colormap.Desaturation); - additivefog = true; - sprite->lightlist = nullptr; // the fuzz effect does not use the sector's light level so splitting is not needed. - } - else if (RenderStyle.BlendOp == STYLEOP_Add && RenderStyle.DestAlpha == STYLEALPHA_One) - { - additivefog = true; - } - } - else if (sprite->modelframe == nullptr) - { - // This still needs to set the texture mode. As blend mode it will always use GL_ONE/GL_ZERO - gl_RenderState.SetTextureMode(RenderStyle); - gl_RenderState.SetDepthBias(-1, -128); - } - if (RenderStyle.BlendOp != STYLEOP_Shadow) - { - if (level.HasDynamicLights && !isFullbrightScene() && !sprite->fullbright) - { - if ( sprite->dynlightindex == -1) // only set if we got no light buffer index. This covers all cases where sprite lighting is used. - { - float out[3]; - GetDynSpriteLight(gl_light_sprites ? sprite->actor : nullptr, gl_light_particles ? sprite->particle : nullptr, out); - gl_RenderState.SetDynLight(out[0], out[1], out[2]); - } - } - sector_t *cursec = sprite->actor ? sprite->actor->Sector : sprite->particle ? sprite->particle->subsector->sector : nullptr; - if (cursec != nullptr) - { - const PalEntry finalcol = sprite->fullbright - ? sprite->ThingColor - : sprite->ThingColor.Modulate(cursec->SpecialColors[sector_t::sprites]); - - gl_RenderState.SetObjectColor(finalcol); - } - SetColor(sprite->lightlevel, rel, sprite->Colormap, sprite->trans); - } - - - if (sprite->Colormap.FadeColor.isBlack()) sprite->foglevel = sprite->lightlevel; - - if (RenderStyle.Flags & STYLEF_FadeToBlack) - { - sprite->Colormap.FadeColor=0; - additivefog = true; - } - - if (RenderStyle.BlendOp == STYLEOP_RevSub || RenderStyle.BlendOp == STYLEOP_Sub) - { - if (!sprite->modelframe) - { - // non-black fog with subtractive style needs special treatment - if (!sprite->Colormap.FadeColor.isBlack()) - { - foglayer = true; - // Due to the two-layer approach we need to force an alpha test that lets everything pass - gl_RenderState.AlphaFunc(Alpha_Greater, 0); - } - } - else RenderStyle.BlendOp = STYLEOP_Fuzz; // subtractive with models is not going to work. - } - - if (!foglayer) SetFog(sprite->foglevel, rel, &sprite->Colormap, additivefog); - else - { - gl_RenderState.EnableFog(false); - gl_RenderState.SetFog(0, 0); - } - - if (sprite->gltexture) gl_RenderState.ApplyMaterial(sprite->gltexture, CLAMP_XY, sprite->translation, sprite->OverrideShader); - else if (!sprite->modelframe) gl_RenderState.EnableTexture(false); - - //SetColor(lightlevel, rel, Colormap, trans); - - unsigned int iter = sprite->lightlist? sprite->lightlist->Size() : 1; - bool clipping = false; - auto lightlist = sprite->lightlist; - if (lightlist || sprite->topclip != LARGE_VALUE || sprite->bottomclip != -LARGE_VALUE) - { - clipping = true; - gl_RenderState.EnableSplit(true); - } - - secplane_t bottomp = { { 0, 0, -1. }, sprite->bottomclip }; - secplane_t topp = { { 0, 0, -1. }, sprite->topclip }; - for (unsigned i = 0; i < iter; i++) - { - if (lightlist) - { - // set up the light slice - secplane_t *topplane = i == 0 ? &topp : &(*lightlist)[i].plane; - secplane_t *lowplane = i == (*lightlist).Size() - 1 ? &bottomp : &(*lightlist)[i + 1].plane; - - int thislight = (*lightlist)[i].caster != nullptr ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : sprite->lightlevel; - int thisll = sprite->actor == nullptr? thislight : (uint8_t)sprite->actor->Sector->CheckSpriteGlow(thislight, sprite->actor->InterpolatedPosition(vp.TicFrac)); - - FColormap thiscm; - thiscm.CopyFog(sprite->Colormap); - thiscm.CopyFrom3DLight(&(*lightlist)[i]); - if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) - { - thiscm.Decolorize(); - } - - SetColor(thisll, rel, thiscm, sprite->trans); - if (!foglayer) - { - SetFog(thislight, rel, &thiscm, additivefog); - } - gl_RenderState.SetSplitPlanes(*topplane, *lowplane); - } - else if (clipping) - { - gl_RenderState.SetSplitPlanes(topp, bottomp); - } - - if (!sprite->modelframe) - { - gl_RenderState.Apply(); - - gl_RenderState.SetNormal(0, 0, 0); - - if (screen->BuffersArePersistent()) - { - sprite->CreateVertices(this); - } - if (sprite->polyoffset) - { - gl_RenderState.SetDepthBias(-1, -128); - } - - glDrawArrays(GL_TRIANGLE_STRIP, sprite->vertexindex, 4); - - if (foglayer) - { - // If we get here we know that we have colored fog and no fixed colormap. - SetFog(sprite->foglevel, rel, &sprite->Colormap, additivefog); - gl_RenderState.SetTextureMode(TM_FOGLAYER); - gl_RenderState.SetRenderStyle(STYLE_Translucent); - gl_RenderState.Apply(); - glDrawArrays(GL_TRIANGLE_STRIP, sprite->vertexindex, 4); - gl_RenderState.SetTextureMode(TM_NORMAL); - } - } - else - { - FGLModelRenderer renderer(this, sprite->dynlightindex); - renderer.RenderModel(sprite->x, sprite->y, sprite->z, sprite->modelframe, sprite->actor, vp.TicFrac); - } - } - - if (clipping) - { - gl_RenderState.EnableSplit(false); - } - - if (pass==GLPASS_TRANSLUCENT) - { - gl_RenderState.EnableBrightmap(true); - gl_RenderState.SetRenderStyle(STYLE_Translucent); - gl_RenderState.SetTextureMode(TM_NORMAL); - if (sprite->actor != nullptr && (sprite->actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE) - { - gl_RenderState.ClearDepthBias(); - } - } - else if (sprite->modelframe == nullptr) - { - gl_RenderState.ClearDepthBias(); - } - - gl_RenderState.SetObjectColor(0xffffffff); - gl_RenderState.EnableTexture(true); - gl_RenderState.SetDynLight(0,0,0); -} - - -//========================================================================== -// -// -// -//========================================================================== -void FDrawInfo::AddSprite(GLSprite *sprite, bool translucent) -{ - int list; - // [BB] Allow models to be drawn in the GLDL_TRANSLUCENT pass. - if (translucent || sprite->actor == nullptr || (!sprite->modelframe && (sprite->actor->renderflags & RF_SPRITETYPEMASK) != RF_WALLSPRITE)) - { - list = GLDL_TRANSLUCENT; - } - else - { - list = GLDL_MODELS; - } - - auto newsprt = drawlists[list].NewSprite(); - *newsprt = *sprite; -} - diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 6e4145cae..83d09c6f0 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -30,7 +30,6 @@ #include "gl_load/gl_interface.h" #include "hwrenderer/utility/hw_cvars.h" -#include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_renderer.h" #include "gl/data/gl_vertexbuffer.h" #include "gl/dynlights/gl_lightbuffer.h" diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 586300ddc..8e5ed90fd 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -294,8 +294,6 @@ public: void DrawDecals(FRenderState &state, TArray &decals); - virtual void DrawSprite(GLSprite *sprite, int pass) = 0; - void ProcessLowerMinisegs(TArray &lowersegs); virtual void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) = 0; @@ -315,6 +313,9 @@ public: virtual void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0; virtual void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0; + virtual void DrawModel(GLSprite *spr, FRenderState &state) = 0; + + // Immediate render state change commands. These only change infrequently and should not clutter the render state. virtual void SetDepthMask(bool on) = 0; diff --git a/src/hwrenderer/scene/hw_drawlist.cpp b/src/hwrenderer/scene/hw_drawlist.cpp index 0b5d676b4..59a95c259 100644 --- a/src/hwrenderer/scene/hw_drawlist.cpp +++ b/src/hwrenderer/scene/hw_drawlist.cpp @@ -771,7 +771,7 @@ GLSprite *HWDrawList::NewSprite() // // //========================================================================== -void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, int pass, int i, bool trans) +void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, int i) { switch(drawitems[i].rendertype) { @@ -797,7 +797,7 @@ void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, i { GLSprite * s= sprites[drawitems[i].index]; RenderSprite.Clock(); - di->DrawSprite(s, pass); + s->DrawSprite(di, state, translucent); RenderSprite.Unclock(); } break; @@ -809,11 +809,11 @@ void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, i // // //========================================================================== -void HWDrawList::Draw(HWDrawInfo *di, FRenderState &state, bool translucent, int pass, bool trans) +void HWDrawList::Draw(HWDrawInfo *di, FRenderState &state, bool translucent) { for (unsigned i = 0; i < drawitems.Size(); i++) { - DoDraw(di, state, translucent, pass, i, trans); + DoDraw(di, state, translucent, i); } } diff --git a/src/hwrenderer/scene/hw_drawlist.h b/src/hwrenderer/scene/hw_drawlist.h index ebda38095..3756533b6 100644 --- a/src/hwrenderer/scene/hw_drawlist.h +++ b/src/hwrenderer/scene/hw_drawlist.h @@ -103,8 +103,8 @@ public: SortNode * DoSort(HWDrawInfo *di, SortNode * head); void Sort(HWDrawInfo *di); - void DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, int pass, int i, bool trans); - void Draw(HWDrawInfo *di, FRenderState &state, bool translucent, int pass, bool trans = false); + void DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, int i); + void Draw(HWDrawInfo *di, FRenderState &state, bool translucent); void DrawWalls(HWDrawInfo *di, FRenderState &state, bool translucent); void DrawFlats(HWDrawInfo *di, FRenderState &state, bool translucent); diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 4d4b2df68..97b7ddeb5 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -401,12 +401,14 @@ public: public: - GLSprite() {} + GLSprite() = default; void CreateVertices(HWDrawInfo *di); void PutSprite(HWDrawInfo *di, bool translucent); void Process(HWDrawInfo *di, AActor* thing,sector_t * sector, area_t in_area, int thruportal = false); void ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *sector);//, int shade, int fakeside) + void DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent); + GLSprite(const GLSprite &other) { memcpy(this, &other, sizeof(GLSprite)); diff --git a/src/hwrenderer/scene/hw_sprites.cpp b/src/hwrenderer/scene/hw_sprites.cpp index e8917745a..5c0c6f4b2 100644 --- a/src/hwrenderer/scene/hw_sprites.cpp +++ b/src/hwrenderer/scene/hw_sprites.cpp @@ -52,6 +52,7 @@ #include "hwrenderer/utility/hw_lighting.h" #include "hwrenderer/textures/hw_material.h" #include "hwrenderer/dynlights/hw_dynlightdata.h" +#include "hw_renderstate.h" extern TArray sprites; extern TArray SpriteFrames; @@ -63,6 +64,238 @@ EXTERN_CVAR(Bool, r_debug_disable_vis_filter) EXTERN_CVAR(Float, transsouls) +//========================================================================== +// +// +// +//========================================================================== + +void GLSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) +{ + bool additivefog = false; + bool foglayer = false; + int rel = fullbright ? 0 : getExtraLight(); + auto &vp = di->Viewpoint; + + if (translucent) + { + // The translucent pass requires special setup for the various modes. + + // for special render styles brightmaps would not look good - especially for subtractive. + if (RenderStyle.BlendOp != STYLEOP_Add) + { + state.EnableBrightmap(false); + } + + // Optionally use STYLE_ColorBlend in place of STYLE_Add for fullbright items. + if (RenderStyle == LegacyRenderStyles[STYLE_Add] && trans > 1.f - FLT_EPSILON && + gl_usecolorblending && !di->isFullbrightScene() && actor && + fullbright && gltexture && !gltexture->tex->GetTranslucency()) + { + RenderStyle = LegacyRenderStyles[STYLE_ColorBlend]; + } + + state.SetRenderStyle(RenderStyle); + state.SetTextureMode(RenderStyle); + + if (hw_styleflags == STYLEHW_NoAlphaTest) + { + state.AlphaFunc(Alpha_GEqual, 0.f); + } + else + { + state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + } + + if (RenderStyle.BlendOp == STYLEOP_Shadow) + { + float fuzzalpha = 0.44f; + float minalpha = 0.1f; + + // fog + fuzz don't work well without some fiddling with the alpha value! + if (!Colormap.FadeColor.isBlack()) + { + float dist = Dist2(vp.Pos.X, vp.Pos.Y, x, y); + int fogd = hw_GetFogDensity(lightlevel, Colormap.FadeColor, Colormap.FogDensity, Colormap.BlendFactor); + + // this value was determined by trial and error and is scale dependent! + float factor = 0.05f + exp(-fogd * dist / 62500.f); + fuzzalpha *= factor; + minalpha *= factor; + } + + state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + state.SetColor(0.2f, 0.2f, 0.2f, fuzzalpha, Colormap.Desaturation); + additivefog = true; + lightlist = nullptr; // the fuzz effect does not use the sector's light level so splitting is not needed. + } + else if (RenderStyle.BlendOp == STYLEOP_Add && RenderStyle.DestAlpha == STYLEALPHA_One) + { + additivefog = true; + } + } + else if (modelframe == nullptr) + { + // This still needs to set the texture mode. As blend mode it will always use GL_ONE/GL_ZERO + state.SetTextureMode(RenderStyle); + state.SetDepthBias(-1, -128); + } + if (RenderStyle.BlendOp != STYLEOP_Shadow) + { + if (level.HasDynamicLights && !di->isFullbrightScene() && !fullbright) + { + if (dynlightindex == -1) // only set if we got no light buffer index. This covers all cases where sprite lighting is used. + { + float out[3]; + di->GetDynSpriteLight(gl_light_sprites ? actor : nullptr, gl_light_particles ? particle : nullptr, out); + state.SetDynLight(out[0], out[1], out[2]); + } + } + sector_t *cursec = actor ? actor->Sector : particle ? particle->subsector->sector : nullptr; + if (cursec != nullptr) + { + const PalEntry finalcol = fullbright + ? ThingColor + : ThingColor.Modulate(cursec->SpecialColors[sector_t::sprites]); + + state.SetObjectColor(finalcol); + } + state.SetColor(lightlevel, rel, di->isFullbrightScene(), Colormap, trans); + } + + + if (Colormap.FadeColor.isBlack()) foglevel = lightlevel; + + if (RenderStyle.Flags & STYLEF_FadeToBlack) + { + Colormap.FadeColor = 0; + additivefog = true; + } + + if (RenderStyle.BlendOp == STYLEOP_RevSub || RenderStyle.BlendOp == STYLEOP_Sub) + { + if (!modelframe) + { + // non-black fog with subtractive style needs special treatment + if (!Colormap.FadeColor.isBlack()) + { + foglayer = true; + // Due to the two-layer approach we need to force an alpha test that lets everything pass + state.AlphaFunc(Alpha_Greater, 0); + } + } + else RenderStyle.BlendOp = STYLEOP_Fuzz; // subtractive with models is not going to work. + } + + if (!foglayer) state.SetFog(foglevel, rel, di->isFullbrightScene(), &Colormap, additivefog); + else + { + state.EnableFog(false); + state.SetFog(0, 0); + } + + if (gltexture) state.SetMaterial(gltexture, CLAMP_XY, translation, OverrideShader); + else if (!modelframe) state.EnableTexture(false); + + //SetColor(lightlevel, rel, Colormap, trans); + + unsigned int iter = lightlist ? lightlist->Size() : 1; + bool clipping = false; + if (lightlist || topclip != LARGE_VALUE || bottomclip != -LARGE_VALUE) + { + clipping = true; + state.EnableSplit(true); + } + + secplane_t bottomp = { { 0, 0, -1. }, bottomclip }; + secplane_t topp = { { 0, 0, -1. }, topclip }; + for (unsigned i = 0; i < iter; i++) + { + if (lightlist) + { + // set up the light slice + secplane_t *topplane = i == 0 ? &topp : &(*lightlist)[i].plane; + secplane_t *lowplane = i == (*lightlist).Size() - 1 ? &bottomp : &(*lightlist)[i + 1].plane; + + int thislight = (*lightlist)[i].caster != nullptr ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; + int thisll = actor == nullptr ? thislight : (uint8_t)actor->Sector->CheckSpriteGlow(thislight, actor->InterpolatedPosition(vp.TicFrac)); + + FColormap thiscm; + thiscm.CopyFog(Colormap); + thiscm.CopyFrom3DLight(&(*lightlist)[i]); + if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) + { + thiscm.Decolorize(); + } + + state.SetColor(thisll, rel, di->isFullbrightScene(), thiscm, trans); + if (!foglayer) + { + state.SetFog(thislight, rel, di->isFullbrightScene(), &thiscm, additivefog); + } + state.SetSplitPlanes(*topplane, *lowplane); + } + else if (clipping) + { + state.SetSplitPlanes(topp, bottomp); + } + + if (!modelframe) + { + state.SetNormal(0, 0, 0); + + if (screen->BuffersArePersistent()) + { + CreateVertices(di); + } + if (polyoffset) + { + state.SetDepthBias(-1, -128); + } + + di->Draw(DT_TriangleStrip, state, vertexindex, 4); + + if (foglayer) + { + // If we get here we know that we have colored fog and no fixed colormap. + state.SetFog(foglevel, rel, false, &Colormap, additivefog); + state.SetTextureMode(TM_FOGLAYER); + state.SetRenderStyle(STYLE_Translucent); + di->Draw(DT_TriangleStrip, state, vertexindex, 4); + state.SetTextureMode(TM_NORMAL); + } + } + else + { + di->DrawModel(this, state); + } + } + + if (clipping) + { + state.EnableSplit(false); + } + + if (translucent) + { + state.EnableBrightmap(true); + state.SetRenderStyle(STYLE_Translucent); + state.SetTextureMode(TM_NORMAL); + if (actor != nullptr && (actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE) + { + state.ClearDepthBias(); + } + } + else if (modelframe == nullptr) + { + state.ClearDepthBias(); + } + + state.SetObjectColor(0xffffffff); + state.EnableTexture(true); + state.SetDynLight(0, 0, 0); +} + //========================================================================== // //