diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 27ae7f6b977..3056bc04bcc 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1071,6 +1071,8 @@ set (PCH_SOURCES core/rendering/scene/hw_portal.cpp core/rendering/scene/hw_skyportal.cpp core/rendering/scene/hw_sky.cpp + core/rendering/scene/hw_setcolor.cpp + core/rendering/scene/hw_lighting.cpp core/console/c_notifybuffer.cpp core/console/d_event.cpp diff --git a/source/common/2d/v_draw.h b/source/common/2d/v_draw.h index 0d25d59999a..fecfc3d9edb 100644 --- a/source/common/2d/v_draw.h +++ b/source/common/2d/v_draw.h @@ -325,3 +325,5 @@ class ScaleOverrider CleanHeight = savedheight; } }; + +void Draw2D(F2DDrawer* drawer, FRenderState& state); diff --git a/source/common/rendering/gl/gl_framebuffer.cpp b/source/common/rendering/gl/gl_framebuffer.cpp index 2ff99b51179..53a24bf0669 100644 --- a/source/common/rendering/gl/gl_framebuffer.cpp +++ b/source/common/rendering/gl/gl_framebuffer.cpp @@ -69,7 +69,6 @@ EXTERN_CVAR(Int, gl_pipeline_depth); void gl_LoadExtensions(); void gl_PrintStartupLog(); -void Draw2D(F2DDrawer *drawer, FRenderState &state); extern bool vid_hdr_active; diff --git a/source/common/rendering/gles/gles_framebuffer.cpp b/source/common/rendering/gles/gles_framebuffer.cpp index f3806f13261..c858e969f93 100644 --- a/source/common/rendering/gles/gles_framebuffer.cpp +++ b/source/common/rendering/gles/gles_framebuffer.cpp @@ -67,8 +67,6 @@ EXTERN_CVAR(Int, gl_pipeline_depth); EXTERN_CVAR(Bool, gl_sort_textures); -void Draw2D(F2DDrawer *drawer, FRenderState &state); - extern bool vid_hdr_active; namespace OpenGLESRenderer diff --git a/source/common/rendering/vulkan/system/vk_framebuffer.cpp b/source/common/rendering/vulkan/system/vk_framebuffer.cpp index 76444dfb9e0..ee64909b48f 100644 --- a/source/common/rendering/vulkan/system/vk_framebuffer.cpp +++ b/source/common/rendering/vulkan/system/vk_framebuffer.cpp @@ -57,8 +57,6 @@ #include "engineerrors.h" #include "c_dispatch.h" -void Draw2D(F2DDrawer *drawer, FRenderState &state); - EXTERN_CVAR(Bool, r_drawvoxels) EXTERN_CVAR(Int, gl_tonemap) EXTERN_CVAR(Int, screenblocks) diff --git a/source/core/rendering/scene/hw_drawinfo.h b/source/core/rendering/scene/hw_drawinfo.h index 70dde41b960..d3e5ed82c23 100644 --- a/source/core/rendering/scene/hw_drawinfo.h +++ b/source/core/rendering/scene/hw_drawinfo.h @@ -10,6 +10,8 @@ #include "hw_bunchdrawer.h" //#include "r_viewpoint.h" +EXTERN_CVAR(Int, hw_lightmode) + enum EDrawMode { DM_MAINVIEW, @@ -133,6 +135,13 @@ struct HWDrawInfo //void RenderThings(sectortype * sub, sectortype * sector); //void RenderParticles(sectortype *sub, sectortype *front); void SetColor(FRenderState &state, int sectorlightlevel, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon = false); + int CalcLightLevel(int lightlevel, int rellight, bool weapon, int blendfactor); + PalEntry CalcLightColor(int light, PalEntry pe, int blendfactor); + void SetShaderLight(FRenderState& state, float level, float olight); + void SetFog(FRenderState& state, int lightlevel, int rellight, bool fullbright, const FColormap* cmap, bool isadditive); + + float GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor); + public: void SetCameraPos(const DVector3 &pos) @@ -187,36 +196,22 @@ struct HWDrawInfo void AddSprite(HWSprite *sprite, bool translucent); - bool isSoftwareLighting() const - { - return true;// lightmode == ELightMode::ZDoomSoftware || lightmode == ELightMode::DoomSoftware || lightmode == ELightMode::Build; - } - bool isBuildSoftwareLighting() const { - return true;// lightmode == ELightMode::Build; - } - - bool isDoomSoftwareLighting() const - { - return false;// lightmode == ELightMode::ZDoomSoftware || lightmode == ELightMode::DoomSoftware; + return hw_lightmode == 0; } bool isDarkLightMode() const { - return false;// lightmode == ELightMode::Doom || lightmode == ELightMode::DoomDark; - } - - void SetFallbackLightMode() - { - //lightmode = ELightMode::Doom; + return hw_lightmode == 2; } - }; void CleanSWDrawer(); -//sectortype* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); -//void WriteSavePic(player_t* player, FileWriter* file, int width, int height); -//sectortype* RenderView(player_t* player); + +inline int hw_ClampLight(int lightlevel) +{ + return clamp(lightlevel, 0, 255); +} diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index e0e3765a593..563e77165ef 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -415,39 +415,7 @@ inline void SetSpriteTranslucency(const tspritetype* sprite, float& alpha, FRend alpha *= 1.f - sprite->ownerActor->sprext.alpha; } -//========================================================================== -// -// -// -//========================================================================== extern PalEntry GlobalMapFog; extern float GlobalFogDensity; -__forceinline void SetLightAndFog(FRenderState& state, PalEntry fade, int palette, int shade, float visibility, float alpha) -{ - // Fog must be done before the texture so that the texture selector can override it. - bool foggy = (GlobalMapFog || (fade & 0xffffff)); - auto ShadeDiv = lookups.tables[palette].ShadeFactor; - if (shade == 127) state.SetObjectColor(0xff000000); // 127 is generally used for shadow objects that must be black, even in foggy areas. - - // Disable brightmaps if non-black fog is used. - if (ShadeDiv >= 1 / 1000.f && foggy) - { - state.EnableFog(1); - float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); - state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); - state.SetSoftLightLevel(255); - state.SetLightParms(128.f, 1 / 1000.f); - } - else - { - state.EnableFog(0); - state.SetFog(0, 0); - state.SetSoftLightLevel(gl_fogmode != 0 && ShadeDiv >= 1 / 1000.f ? max(0, 255 - Scale(shade, 255, numshades)) : 255); - state.SetLightParms(visibility, ShadeDiv / (numshades - 2)); - } - - // The shade rgb from the tint is ignored here. - state.SetColor(globalr * (1 / 255.f), globalg * (1 / 255.f), globalb * (1 / 255.f), alpha); -} - +void SetLightAndFog(HWDrawInfo* di, FRenderState& state, PalEntry fade, int palette, int shade, float visibility, float alpha); diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index 697653e3099..98c8ba9d25b 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -222,7 +222,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) else state.SetNormal({ 0, -1, 0 }); } - SetLightAndFog(state, fade, palette, shade, visibility, alpha); + SetLightAndFog(di, state, fade, palette, shade, visibility, alpha); if (translucent) { diff --git a/source/core/rendering/scene/hw_lighting.cpp b/source/core/rendering/scene/hw_lighting.cpp new file mode 100644 index 00000000000..78ef240ec0e --- /dev/null +++ b/source/core/rendering/scene/hw_lighting.cpp @@ -0,0 +1,185 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2002-2018 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 2 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_light.cpp +** Light level / fog management / dynamic lights +** +**/ + +#include "c_cvars.h" +#include "hw_drawinfo.h" + +// externally settable lighting properties +static float distfogtable[2][256]; // light to fog conversion table for black fog + +CVAR(Int, hw_weaponlight, 8, CVAR_ARCHIVE); + +//========================================================================== +// +// Sets up the fog tables +// +//========================================================================== + +CUSTOM_CVAR(Int, gl_distfog, 70, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + for (int i = 0; i < 256; i++) + { + + if (i < 164) + { + distfogtable[0][i] = (float)((gl_distfog >> 1) + (gl_distfog)*(164 - i) / 164); + } + else if (i < 230) + { + distfogtable[0][i] = (float)((gl_distfog >> 1) - (gl_distfog >> 1)*(i - 164) / (230 - 164)); + } + else distfogtable[0][i] = 0; + + if (i < 128) + { + distfogtable[1][i] = 6.f + (float)((gl_distfog >> 1) + (gl_distfog)*(128 - i) / 48); + } + else if (i < 216) + { + distfogtable[1][i] = (216.f - i) / ((216.f - 128.f)) * gl_distfog / 10; + } + else distfogtable[1][i] = 0; + } +} + +//========================================================================== +// +// Get current light level +// +//========================================================================== + +int HWDrawInfo::CalcLightLevel(int lightlevel, int rellight, bool weapon, int blendfactor) +{ + int light; + + if (lightlevel <= 0) return 0; + + bool darklightmode = isDarkLightMode(); + + if (darklightmode && lightlevel < 192 && !weapon) + { + if (lightlevel > 100) + { + light = xs_CRoundToInt(192.f - (192 - lightlevel)* 1.87f); + if (light + rellight < 20) + { + light = 20 + (light + rellight - 20) / 5; + } + else + { + light += rellight; + } + } + else + { + light = (lightlevel + rellight) / 5; + } + + } + else + { + light=lightlevel+rellight; + } + + // Fake contrast should never turn a positive value into 0. + return clamp(light, 1, 255); +} + +//========================================================================== +// +// Get current light color +// +//========================================================================== + +PalEntry HWDrawInfo::CalcLightColor(int light, PalEntry pe, int blendfactor) +{ + int r,g,b; + + if (blendfactor == 0) + { + r = pe.r * light / 255; + g = pe.g * light / 255; + b = pe.b * light / 255; + } + else + { + // This is what Legacy does with colored light in 3D volumes. No, it doesn't really make sense... + // It also doesn't translate well to software style lighting. + int mixlight = light * (255 - blendfactor); + + r = (mixlight + pe.r * blendfactor) / 255; + g = (mixlight + pe.g * blendfactor) / 255; + b = (mixlight + pe.b * blendfactor) / 255; + } + return PalEntry(255, uint8_t(r), uint8_t(g), uint8_t(b)); +} + +//========================================================================== +// +// calculates the current fog density +// +//========================================================================== + +float HWDrawInfo::GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor) +{ + float density; + + if (sectorfogdensity != 0) + { + // case 1: Sector has an explicit fog density set. + density = (float)sectorfogdensity; + } + else if ((fogcolor.d & 0xffffff) == 0) + { + // case 2: black fog + density = distfogtable[0][hw_ClampLight(lightlevel)]; + //density = distfogtable[lightmode != ELightMode::LinearStandard][hw_ClampLight(lightlevel)]; + } +#if 0 + else if (Level->outsidefogdensity != 0 && APART(Level->info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (Level->info->outsidefog & 0xffffff)) + { + // case 3. outsidefogdensity has already been set as needed + density = (float)Level->outsidefogdensity; + } + else if (Level->fogdensity != 0) + { + // case 4: level has fog density set + density = (float)Level->fogdensity; + } +#endif + else if (lightlevel < 248) + { + // case 5: use light level + density = (float)clamp(255 - lightlevel, 30, 255); + } + else + { + density = 0.f; + } + return density; +} + diff --git a/source/core/rendering/scene/hw_setcolor.cpp b/source/core/rendering/scene/hw_setcolor.cpp new file mode 100644 index 00000000000..9ab1c729558 --- /dev/null +++ b/source/core/rendering/scene/hw_setcolor.cpp @@ -0,0 +1,187 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2000-2018 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 2 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/ +// +//-------------------------------------------------------------------------- +// +/* +** hw_renderstate.cpp +** hardware independent part of render state. +** +*/ + +#include "hw_renderstate.h" +#include "hw_drawstructs.h" +#include "hw_portal.h" +#include "hw_cvars.h" + +CVAR(Int, hw_lightmode, 0, CVAR_ARCHIVE) + +//========================================================================== +// +// set current light color +// +//========================================================================== +void HWDrawInfo::SetColor(FRenderState &state, int sectorlightlevel, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon) +{ + if (fullbright) + { + state.SetColorAlpha(0xffffff, alpha, 0); + state.SetNoSoftLightLevel(); + } + else + { + int hwlightlevel = CalcLightLevel(sectorlightlevel, rellight, weapon, cm.BlendFactor); + PalEntry pe = CalcLightColor(hwlightlevel, cm.LightColor, cm.BlendFactor); + state.SetColorAlpha(pe, alpha, cm.Desaturation); + state.SetNoSoftLightLevel(); + } +} + +//========================================================================== +// +// Lighting stuff +// +//========================================================================== + +void HWDrawInfo::SetShaderLight(FRenderState &state, float level, float olight) +{ + const float MAXDIST = 256.f; + const float THRESHOLD = 96.f; + const float FACTOR = 0.75f; + + if (level > 0) + { + float lightdist, lightfactor; + + if (olight < THRESHOLD) + { + lightdist = (MAXDIST / 2) + (olight * MAXDIST / THRESHOLD / 2); + olight = THRESHOLD; + } + else lightdist = MAXDIST; + + lightfactor = 1.f + ((olight / level) - 1.f) * FACTOR; + if (lightfactor == 1.f) lightdist = 0.f; // save some code in the shader + state.SetLightParms(lightfactor, lightdist); + } + else + { + state.SetLightParms(1.f, 0.f); + } +} + + +//========================================================================== +// +// Sets the fog for the current polygon +// +//========================================================================== + +void HWDrawInfo::SetFog(FRenderState &state, int lightlevel, int rellight, bool fullbright, const FColormap *cmap, bool isadditive) +{ + PalEntry fogcolor; + float fogdensity; + + if (cmap != nullptr && !fullbright) + { + fogcolor = cmap->FadeColor; + fogdensity = GetFogDensity(lightlevel, fogcolor, cmap->FogDensity, cmap->BlendFactor); + fogcolor.a = 0; + } + else + { + fogcolor = 0; + fogdensity = 0; + } + + // Make fog a little denser when inside a skybox + if (portalState.inskybox) fogdensity += fogdensity / 2; + + + // no fog in enhanced vision modes! + if (fogdensity == 0 || gl_fogmode == 0) + { + state.EnableFog(false); + state.SetFog(0, 0); + } + else + { +#if 0 + if (lightmode == ELightMode::Doom) + { + float light = (float)CalcLightLevel(lightlevel, rellight, false, cmap->BlendFactor); + SetShaderLight(state, light, lightlevel); + } + else +#endif + { + state.SetLightParms(1.f, 0.f); + } + + // For additive rendering using the regular fog color here would mean applying it twice + // so always use black + if (isadditive) + { + fogcolor = 0; + } + + state.EnableFog(true); + state.SetFog(fogcolor, fogdensity); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void SetLightAndFog(HWDrawInfo* di, FRenderState& state, PalEntry fade, int palette, int shade, float visibility, float alpha) +{ + if (!di->isBuildSoftwareLighting()) + { + + return; + } + // Fog must be done before the texture so that the texture selector can override it. + bool foggy = (GlobalMapFog || (fade & 0xffffff)); + auto ShadeDiv = lookups.tables[palette].ShadeFactor; + if (shade == 127) state.SetObjectColor(0xff000000); // 127 is generally used for shadow objects that must be black, even in foggy areas. + + // Disable brightmaps if non-black fog is used. + if (ShadeDiv >= 1 / 1000.f && foggy) + { + state.EnableFog(1); + float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); + state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); + state.SetSoftLightLevel(255); + state.SetLightParms(128.f, 1 / 1000.f); + } + else + { + state.EnableFog(0); + state.SetFog(0, 0); + state.SetSoftLightLevel(gl_fogmode != 0 && ShadeDiv >= 1 / 1000.f ? max(0, 255 - Scale(shade, 255, numshades)) : 255); + state.SetLightParms(visibility, ShadeDiv / (numshades - 2)); + } + + // The shade rgb from the tint is ignored here. + state.SetColor(globalr * (1 / 255.f), globalg * (1 / 255.f), globalb * (1 / 255.f), alpha); +} + diff --git a/source/core/rendering/scene/hw_skyportal.cpp b/source/core/rendering/scene/hw_skyportal.cpp index 7dba7139a9b..29126dc5eab 100644 --- a/source/core/rendering/scene/hw_skyportal.cpp +++ b/source/core/rendering/scene/hw_skyportal.cpp @@ -38,11 +38,7 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) int indexed = hw_int_useindexedcolortextures; hw_int_useindexedcolortextures = false; // this code does not work with indexed textures. - if (di->isSoftwareLighting()) - { - //di->SetFallbackLightMode(); - state.SetNoSoftLightLevel(); - } + state.SetNoSoftLightLevel(); state.ResetColor(); state.EnableFog(false); diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index da88a5fc243..d1c73b869a9 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -108,7 +108,7 @@ void HWSprite::DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent) else RenderStyle.BlendOp = STYLEOP_Fuzz; // subtractive with models is not going to work. } - SetLightAndFog(state, fade, palette, shade, visibility, alpha); + SetLightAndFog(di, state, fade, palette, shade, visibility, alpha); if (shade >= numshades) state.SetObjectColor(0xff000000); // make sure that nothing lights this up again. diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index 8b390a01879..9bad221d121 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -123,7 +123,7 @@ void HWWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state) if (gl_fogmode)// && !di->isFullbrightScene()) { state.EnableDrawBufferAttachments(false); - SetLightAndFog(state, fade, palette, shade, visibility, alpha); + SetLightAndFog(di, state, fade, palette, shade, visibility, alpha); state.SetEffect(EFF_FOGBOUNDARY); state.AlphaFunc(Alpha_GEqual, 0.f); state.SetDepthBias(-1, -128); @@ -150,7 +150,7 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) // Use sphere mapping for this state.SetEffect(EFF_SPHEREMAP); - SetLightAndFog(state, fade, palette, min(shade, numshades), visibility, alpha); + SetLightAndFog(di, state, fade, palette, min(shade, numshades), visibility, alpha); state.SetColor(PalEntry(25, globalr >> 1, globalg >> 1, globalb >> 1)); state.SetRenderStyle(STYLE_Add); @@ -177,7 +177,7 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) { - SetLightAndFog(state, fade, palette, shade, visibility, alpha); + SetLightAndFog(di, state, fade, palette, shade, visibility, alpha); state.SetMaterial(texture, UF_Texture, 0, (flags & (HWF_CLAMPX | HWF_CLAMPY)), TRANSLATION(Translation_Remap + curbasepal, palette), -1); diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index 5b35bb65830..c2174e9bf6a 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -65,7 +65,6 @@ EXTERN_CVAR(Bool, gl_texture) static int BufferLock = 0; TArray matrixArray; -void Draw2D(F2DDrawer* drawer, FRenderState& state); GLInstance GLInterface;