From cae710bd59f0031410700d8f69c3ff022920fc01 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 10 Nov 2019 10:01:31 +0100 Subject: [PATCH] - fixed alpha threshold. Not only is this a deprecated feature - it also does not work right when complex lighting is at play, it must be done in the shader to get proper results. --- source/CMakeLists.txt | 1 + source/build/src/engine.cpp | 2 + source/common/2d/v_draw.h | 18 ++- source/common/console/c_console.cpp | 10 -- source/common/utility/stats.cpp | 143 ++++++++++++++++++ .../{build/include => common/utility}/stats.h | 37 +++++ source/glbackend/gl_renderstate.h | 3 + source/glbackend/gl_shader.cpp | 1 + source/glbackend/gl_shader.h | 1 + source/glbackend/gl_texture.cpp | 3 +- source/glbackend/glbackend.cpp | 12 +- source/glbackend/glbackend.h | 13 +- source/glbackend/hw_draw2d.cpp | 2 - .../demolition/shaders/glsl/polymost.fp | 3 +- 14 files changed, 221 insertions(+), 28 deletions(-) create mode 100644 source/common/utility/stats.cpp rename source/{build/include => common/utility}/stats.h (86%) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 542717654..75519dab3 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -811,6 +811,7 @@ set (PCH_SOURCES common/utility/m_png.cpp common/utility/memarena.cpp common/utility/sc_man.cpp + common/utility/stats.cpp common/filesystem/filesystem.cpp common/filesystem/ancientzip.cpp diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index c11e2c805..03bccbb43 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -25,6 +25,7 @@ #include "c_console.h" #include "v_2ddrawer.h" #include "imgui.h" +#include "stats.h" #ifdef USE_OPENGL # include "glsurface.h" @@ -10238,6 +10239,7 @@ void videoNextPage(void) } // Draw the console plus debug output on top of everything else. + FStat::PrintStat(); C_DrawConsole(); GLInterface.Draw2D(&twod); diff --git a/source/common/2d/v_draw.h b/source/common/2d/v_draw.h index b289baab6..3a8bfe67a 100644 --- a/source/common/2d/v_draw.h +++ b/source/common/2d/v_draw.h @@ -1,7 +1,8 @@ #pragma once #include "drawparms.h" - +#include "c_cvars.h" +// Undo Windows's forced #defines #ifdef DrawText #undef DrawText #endif @@ -17,6 +18,7 @@ extern ScreenDummy* screen; int GetUIScale(int altval); int GetConScale(int altval); + // [RH] Stretch values to make a 320x200 image best fit the screen // without using fractional steppings extern int CleanXfac, CleanYfac; @@ -45,3 +47,17 @@ void DrawTexture(F2DDrawer *drawer, FTexture* img, double x, double y, int tags_ void DrawChar (F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...); void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...); void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char32_t *string, int tag_first, ...); + +EXTERN_CVAR(Int, con_scaletext) // Scale notify text at high resolutions? +EXTERN_CVAR(Int, con_scale) + +inline int active_con_scaletext(bool newconfont = false) +{ + return newconfont ? GetConScale(con_scaletext) : GetUIScale(con_scaletext); +} + +inline int active_con_scale() +{ + return GetConScale(con_scale); +} + diff --git a/source/common/console/c_console.cpp b/source/common/console/c_console.cpp index f7cfb6369..0a029990a 100644 --- a/source/common/console/c_console.cpp +++ b/source/common/console/c_console.cpp @@ -155,16 +155,6 @@ CVAR(Int, developer, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) EXTERN_CVAR(Int, uiscale); -inline int active_con_scaletext(bool newconfont = false) -{ - return newconfont ? GetConScale(con_scaletext) : GetUIScale(con_scaletext); -} - -inline int active_con_scale() -{ - return GetConScale(con_scale); -} - bool generic_ui = true; diff --git a/source/common/utility/stats.cpp b/source/common/utility/stats.cpp new file mode 100644 index 000000000..bda6e7ec0 --- /dev/null +++ b/source/common/utility/stats.cpp @@ -0,0 +1,143 @@ +/* +** stats.cpp +** Performance-monitoring statistics +** +**--------------------------------------------------------------------------- +** Copyright 1998-2006 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "stats.h" +#include "v_draw.h" +#include "v_text.h" +#include "v_font.h" +#include "c_console.h" +#include "c_dispatch.h" +#include "printf.h" + +FStat *FStat::FirstStat; + +FStat::FStat (const char *name) +{ + m_Name = name; + m_Active = false; + m_Next = FirstStat; + FirstStat = this; +} + +FStat::~FStat () +{ + FStat **prev = &FirstStat; + + while (*prev && *prev != this) + prev = &((*prev)->m_Next)->m_Next; + + if (*prev == this) + *prev = m_Next; +} + +FStat *FStat::FindStat (const char *name) +{ + FStat *stat = FirstStat; + + while (stat && stricmp (name, stat->m_Name)) + stat = stat->m_Next; + + return stat; +} + +void FStat::ToggleStat (const char *name) +{ + FStat *stat = FindStat (name); + if (stat) + stat->ToggleStat (); + else + Printf ("Unknown stat: %s\n", name); +} + +void FStat::ToggleStat () +{ + m_Active = !m_Active; +} + +void FStat::PrintStat () +{ + int textScale = active_con_scale(); + + int fontheight = NewConsoleFont->GetHeight() + 1; + int y = screen->GetHeight() / textScale; + int count = 0; + + for (FStat *stat = FirstStat; stat != NULL; stat = stat->m_Next) + { + if (stat->m_Active) + { + FString stattext(stat->GetStats()); + + if (stattext.Len() > 0) + { + y -= fontheight; // there's at least one line of text + for (unsigned i = 0; i < stattext.Len()-1; i++) + { + // Count number of linefeeds but ignore terminating ones. + if (stattext[i] == '\n') y -= fontheight; + } + DrawText(&twod, NewConsoleFont, CR_GREEN, 5 / textScale, y, stattext, + DTA_VirtualWidth, screen->GetWidth() / textScale, + DTA_VirtualHeight, screen->GetHeight() / textScale, + DTA_KeepRatio, true, TAG_DONE); + count++; + } + } + } +} + +void FStat::DumpRegisteredStats () +{ + FStat *stat = FirstStat; + + Printf ("Available stats:\n"); + while (stat) + { + Printf (" %c%s\n", stat->m_Active ? '*' : ' ', stat->m_Name); + stat = stat->m_Next; + } +} + +CCMD (stat) +{ + if (argv.argc() != 2) + { + Printf ("Usage: stat \n"); + FStat::DumpRegisteredStats (); + } + else + { + FStat::ToggleStat (argv[1]); + } +} diff --git a/source/build/include/stats.h b/source/common/utility/stats.h similarity index 86% rename from source/build/include/stats.h rename to source/common/utility/stats.h index 2df42e333..ede0424c6 100644 --- a/source/build/include/stats.h +++ b/source/common/utility/stats.h @@ -34,6 +34,8 @@ #ifndef __STATS_H__ #define __STATS_H__ +#include "zstring.h" + #if !defined _WIN32 && !defined __APPLE__ #ifdef NO_CLOCK_GETTIME @@ -206,4 +208,39 @@ private: }; + +class FStat +{ +public: + FStat (const char *name); + virtual ~FStat (); + + virtual FString GetStats () = 0; + + void ToggleStat (); + bool isActive() const + { + return m_Active; + } + + static void PrintStat (); + static FStat *FindStat (const char *name); + static void ToggleStat (const char *name); + static void DumpRegisteredStats (); + +private: + FStat *m_Next; + const char *m_Name; + bool m_Active; + + static FStat *FirstStat; +}; + +#define ADD_STAT(n) \ + static class Stat_##n : public FStat { \ + public: \ + Stat_##n () : FStat (#n) {} \ + FString GetStats (); } Istaticstat##n; \ + FString Stat_##n::GetStats () + #endif //__STATS_H__ diff --git a/source/glbackend/gl_renderstate.h b/source/glbackend/gl_renderstate.h index 20ed3afba..20ed2ea52 100644 --- a/source/glbackend/gl_renderstate.h +++ b/source/glbackend/gl_renderstate.h @@ -34,6 +34,9 @@ struct PolymostRenderState float NPOTEmulationFactor = 1.f; float NPOTEmulationXOffset; float Brightness = 1.f; + float AlphaThreshold = 0.5f; + bool AlphaTest = true; + PalEntry FogColor; IVertexBuffer* VertexBuffer = nullptr; diff --git a/source/glbackend/gl_shader.cpp b/source/glbackend/gl_shader.cpp index 971e845d0..3f3ddcd29 100644 --- a/source/glbackend/gl_shader.cpp +++ b/source/glbackend/gl_shader.cpp @@ -143,6 +143,7 @@ bool PolymostShader::Load(const char * name, const char * vert_prog, const char NPOTEmulationXOffset.Init(hShader, "u_npotEmulationXOffset"); Brightness.Init(hShader, "u_brightness"); FogColor.Init(hShader, "u_fogColor"); + AlphaThreshold.Init(hShader, "u_alphaThreshold"); RotMatrix.Init(hShader, "u_rotMatrix"); ModelMatrix.Init(hShader, "u_modelMatrix"); diff --git a/source/glbackend/gl_shader.h b/source/glbackend/gl_shader.h index a86afc804..39290e299 100644 --- a/source/glbackend/gl_shader.h +++ b/source/glbackend/gl_shader.h @@ -43,6 +43,7 @@ public: FBufferedUniform1f NPOTEmulationFactor; FBufferedUniform1f NPOTEmulationXOffset; FBufferedUniform1f Brightness; + FBufferedUniform1f AlphaThreshold; FBufferedUniformPalEntry FogColor; FUniformMatrix4f RotMatrix; diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index 28bee5704..879b57b89 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -281,7 +281,7 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int if (TextureType == TT_HICREPLACE) { al = ((unsigned)picnum < MAXTILES && alphahackarray[picnum] != 0) ? alphahackarray[picnum] * (1.f / 255.f) : - (tex->alphaThreshold >= 0.f ? tex->alphaThreshold : 0.f); + (tex->alphaThreshold >= 0 ? tex->alphaThreshold * (1.f / 255.f) : 0.f); } GLInterface.SetAlphaThreshold(al); return true; @@ -302,6 +302,7 @@ bool GLInstance::SetNamedTexture(FTexture* tex, int palette, int sampler) renderState.Flags &= ~RF_UsePalette; BindTexture(0, mtex, sampler); + GLInterface.SetAlphaThreshold(tex->isTranslucent()? 0.f : 0.5f); return true; } diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index 84f93f0ae..4bc88cfb9 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -315,12 +315,6 @@ void GLInstance::EnableBlend(bool on) else glDisable (GL_BLEND); } -void GLInstance::EnableAlphaTest(bool on) -{ - if (on) glEnable (GL_ALPHA_TEST); - else glDisable (GL_ALPHA_TEST); -} - void GLInstance::EnableDepthTest(bool on) { if (on) glEnable (GL_DEPTH_TEST); @@ -449,11 +443,6 @@ void GLInstance::ClearDepth() glClear(GL_DEPTH_BUFFER_BIT); } -void GLInstance::SetAlphaThreshold(float al) -{ - glAlphaFunc(GL_GREATER, al); -} - void GLInstance::SetViewport(int x, int y, int w, int h) { glViewport(x, y, w, h); @@ -524,6 +513,7 @@ void PolymostRenderState::Apply(PolymostShader* shader) shader->Flags.Set(Flags); shader->NPOTEmulationFactor.Set(NPOTEmulationFactor); shader->NPOTEmulationXOffset.Set(NPOTEmulationXOffset); + shader->AlphaThreshold.Set(AlphaTest ? AlphaThreshold : -1.f); shader->Brightness.Set(Brightness); shader->FogColor.Set(FogColor); diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index 0107449f1..c294d1120 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -240,7 +240,6 @@ public: void UnbindTexture(int texunit); void UnbindAllTextures(); void EnableBlend(bool on); - void EnableAlphaTest(bool on); void EnableDepthTest(bool on); void EnableMultisampling(bool on); void SetVertexBuffer(IVertexBuffer* vb, int offset1, int offset2) @@ -281,7 +280,6 @@ public: void ClearScreen(float r, float g, float b, bool depth); void ClearDepth(); void SetViewport(int x, int y, int w, int h); - void SetAlphaThreshold(float al); void SetWireframe(bool on); void SetPolymostShader(); void SetSurfaceShader(); @@ -403,6 +401,17 @@ public: { return palmanager.FindPalette((uint8_t*)palette); } + + void EnableAlphaTest(bool on) + { + renderState.AlphaTest = on; + } + + void SetAlphaThreshold(float al) + { + renderState.AlphaThreshold = al; + } + FHardwareTexture* CreateIndexedTexture(FTexture* tex); FHardwareTexture* CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false); diff --git a/source/glbackend/hw_draw2d.cpp b/source/glbackend/hw_draw2d.cpp index 76996f700..694e47275 100644 --- a/source/glbackend/hw_draw2d.cpp +++ b/source/glbackend/hw_draw2d.cpp @@ -146,8 +146,6 @@ void GLInstance::Draw2D(F2DDrawer *drawer) SetColor(1, 1, 1); //state.SetColor(1, 1, 1, 1, cmd.mDesaturate); - SetAlphaThreshold(0.0f); - if (cmd.mTexture != nullptr) { auto tex = cmd.mTexture; diff --git a/wadsrc/static/demolition/shaders/glsl/polymost.fp b/wadsrc/static/demolition/shaders/glsl/polymost.fp index cff8da7d0..060e46b1d 100644 --- a/wadsrc/static/demolition/shaders/glsl/polymost.fp +++ b/wadsrc/static/demolition/shaders/glsl/polymost.fp @@ -33,6 +33,7 @@ uniform float u_numShades; uniform float u_shadeDiv; uniform float u_visFactor; uniform int u_flags; +uniform float u_alphaThreshold; uniform float u_npotEmulationFactor; uniform float u_npotEmulationXOffset; @@ -198,9 +199,9 @@ void main() color.rgb = mix(color.rgb, u_fogColor.rgb, shade); } } + if (color.a < u_alphaThreshold) discard; // it's only here that we have the alpha value available to be able to perform the alpha test. if (fullbright == 0.0) color.rgb *= v_color.rgb; color.a *= v_color.a; - color.rgb *= detailColor.rgb; } else {