From ea08fa0a4ed60ca508bbade942bf4918655ab898 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 26 Apr 2020 00:01:04 +0200 Subject: [PATCH] - updated common code. Most of what got added is still unused. # Conflicts: # source/build/src/palette.cpp # Conflicts: # source/build/src/palette.cpp # Conflicts: # source/common/engine/i_interface.h --- source/CMakeLists.txt | 13 +- source/build/src/engine.cpp | 2 + .../rendering/hwrenderer/data/buffers.h | 0 .../hwrenderer/data/hw_renderstate.h | 665 ++++++++++++++++++ .../rendering/hwrenderer/data/renderqueue.h | 0 .../hwrenderer/data/shaderuniforms.h | 0 .../postprocessing/hw_postprocess.cpp | 313 ++++++++- .../postprocessing/hw_postprocess.h | 108 ++- .../postprocessing/hw_postprocess_cvars.cpp | 0 .../postprocessing/hw_postprocess_cvars.h | 0 .../postprocessing/hw_postprocessshader.h | 32 + source/common/rendering/i_video.h | 38 + source/common/rendering/r_videoscale.cpp | 306 ++++++++ source/common/rendering/r_videoscale.h | 40 ++ source/core/colormaps.h | 17 + source/core/console/c_console.cpp | 2 +- source/core/gamecontrol.cpp | 1 + .../hwrenderer/data/hw_viewpointbuffer.cpp | 1 - source/core/rendering/r_videoscale.cpp | 15 +- source/core/rendering/v_video.h | 3 - 20 files changed, 1494 insertions(+), 62 deletions(-) rename source/{core => common}/rendering/hwrenderer/data/buffers.h (100%) create mode 100644 source/common/rendering/hwrenderer/data/hw_renderstate.h rename source/{core => common}/rendering/hwrenderer/data/renderqueue.h (100%) rename source/{core => common}/rendering/hwrenderer/data/shaderuniforms.h (100%) rename source/{core => common}/rendering/hwrenderer/postprocessing/hw_postprocess.cpp (71%) rename source/{core => common}/rendering/hwrenderer/postprocessing/hw_postprocess.h (84%) rename source/{core => common}/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp (100%) rename source/{core => common}/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.h (100%) create mode 100644 source/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h create mode 100644 source/common/rendering/i_video.h create mode 100644 source/common/rendering/r_videoscale.cpp create mode 100644 source/common/rendering/r_videoscale.h create mode 100644 source/core/colormaps.h diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 633a9177e..97b82f158 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -643,7 +643,9 @@ file( GLOB HEADER_FILES common/thirdparty/*.h common/thirdparty/rapidjson/*.h common/thirdparty/math/*h + common/rendering/*.h common/rendering/gl_load/*.h + common/rendering/hwrenderer/data/*.h common/scripting/core/*h common/scripting/vm/*h common/scripting/jit/*h @@ -862,6 +864,10 @@ set (PCH_SOURCES common/objects/dobject.cpp common/objects/dobjgc.cpp common/objects/dobjtype.cpp + common/rendering/r_videoscale.cpp + common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp + common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp + common/rendering/gl_load/gl_interface.cpp common/rendering/gl/gl_debug.cpp common/rendering/gl/gl_hwtexture.cpp @@ -905,7 +911,6 @@ set (PCH_SOURCES #core/input/i_input.cpp core/input/m_joy.cpp - core/rendering/r_videoscale.cpp core/rendering/v_framebuffer.cpp core/rendering/v_video.cpp core/rendering/gl/renderer/gl_renderer.cpp @@ -916,8 +921,6 @@ set (PCH_SOURCES core/rendering/gl/system/gl_buffers.cpp core/rendering/gl/system/gl_framebuffer.cpp core/rendering/hwrenderer/data/flatvertices.cpp - core/rendering/hwrenderer/postprocessing/hw_postprocess.cpp - core/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp core/rendering/hwrenderer/utility/hw_shaderpatcher.cpp ) @@ -1034,6 +1037,7 @@ include_directories( common/fonts common/objects common/rendering + common/rendering/hwrenderer/data common/rendering/gl_load common/rendering/gl common/scripting/vm @@ -1169,6 +1173,9 @@ source_group("Common\\Platforms\\Unix Files" REGULAR_EXPRESSION "^${CMAKE_CURREN source_group("Common\\Platforms\\SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/platform/posix/sdl/.+") source_group("Common\\Platforms\\Win32 Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/platform/win32/.+") source_group("Common\\Rendering" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/.+") +source_group("Common\\Rendering\\Hardware Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/hwrenderer/.+") +source_group("Common\\Rendering\\Hardware Renderer\\Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/hwrenderer/data/.+") +source_group("Common\\Rendering\\Hardware Renderer\\Postprocessing" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/hwrenderer/postprocessing/.+") source_group("Common\\Rendering\\OpenGL Loader" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/gl_load/.+") source_group("Common\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/textures/.+") source_group("Common\\Textures\\Hires" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/textures/hires/.+") diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index a0a00b2c7..17cf1323d 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -2096,10 +2096,12 @@ int32_t enginePostInit(void) { if (!(paletteloaded & PALETTE_MAIN)) I_FatalError("No palette found."); +#if 0 if (!(paletteloaded & PALETTE_SHADE)) I_FatalError("No shade table found."); if (!(paletteloaded & PALETTE_TRANSLUC)) I_FatalError("No translucency table found."); +#endif V_LoadTranslations(); // loading the translations must be delayed until the palettes have been fully set up. lookups.postLoadTables(); diff --git a/source/core/rendering/hwrenderer/data/buffers.h b/source/common/rendering/hwrenderer/data/buffers.h similarity index 100% rename from source/core/rendering/hwrenderer/data/buffers.h rename to source/common/rendering/hwrenderer/data/buffers.h diff --git a/source/common/rendering/hwrenderer/data/hw_renderstate.h b/source/common/rendering/hwrenderer/data/hw_renderstate.h new file mode 100644 index 000000000..24692656a --- /dev/null +++ b/source/common/rendering/hwrenderer/data/hw_renderstate.h @@ -0,0 +1,665 @@ +#pragma once + +#include "v_palette.h" +#include "vectors.h" +#include "matrix.h" +#include "hw_material.h" +#include "texmanip.h" + +struct FColormap; +class IVertexBuffer; +class IIndexBuffer; + +enum EClearTarget +{ + CT_Depth = 1, + CT_Stencil = 2, + CT_Color = 4 +}; + +enum ERenderEffect +{ + EFF_NONE = -1, + EFF_FOGBOUNDARY, + EFF_SPHEREMAP, + EFF_BURN, + EFF_STENCIL, + + MAX_EFFECTS +}; + +enum EAlphaFunc +{ + Alpha_GEqual = 0, + Alpha_Greater = 1 +}; + +enum EDrawType +{ + DT_Points = 0, + DT_Lines = 1, + DT_Triangles = 2, + DT_TriangleFan = 3, + DT_TriangleStrip = 4 +}; + +enum EDepthFunc +{ + DF_Less, + DF_LEqual, + DF_Always +}; + +enum EStencilFlags +{ + SF_AllOn = 0, + SF_ColorMaskOff = 1, + SF_DepthMaskOff = 2, +}; + +enum EStencilOp +{ + SOP_Keep = 0, + SOP_Increment = 1, + SOP_Decrement = 2 +}; + +enum ECull +{ + Cull_None, + Cull_CCW, + Cull_CW +}; + + + +struct FStateVec4 +{ + float vec[4]; + + void Set(float r, float g, float b, float a) + { + vec[0] = r; + vec[1] = g; + vec[2] = b; + vec[3] = a; + } +}; + +struct FMaterialState +{ + FMaterial *mMaterial; + int mClampMode; + int mTranslation; + int mOverrideShader; + bool mChanged; + + void Reset() + { + mMaterial = nullptr; + mTranslation = 0; + mClampMode = CLAMP_NONE; + mOverrideShader = -1; + mChanged = false; + } +}; + +struct FDepthBiasState +{ + float mFactor; + float mUnits; + bool mChanged; + + void Reset() + { + mFactor = 0; + mUnits = 0; + mChanged = false; + } +}; + +enum EPassType +{ + NORMAL_PASS, + GBUFFER_PASS, + MAX_PASS_TYPES +}; + +struct FVector4PalEntry +{ + float r, g, b, a; + + bool operator==(const FVector4PalEntry &other) const + { + return r == other.r && g == other.g && b == other.b && a == other.a; + } + + bool operator!=(const FVector4PalEntry &other) const + { + return r != other.r || g != other.g || b != other.b || a != other.a; + } + + FVector4PalEntry &operator=(PalEntry newvalue) + { + const float normScale = 1.0f / 255.0f; + r = newvalue.r * normScale; + g = newvalue.g * normScale; + b = newvalue.b * normScale; + a = newvalue.a * normScale; + return *this; + } + + FVector4PalEntry& SetIA(PalEntry newvalue) + { + const float normScale = 1.0f / 255.0f; + r = newvalue.r * normScale; + g = newvalue.g * normScale; + b = newvalue.b * normScale; + a = 1; + return *this; + } + + FVector4PalEntry& SetFlt(float v1, float v2, float v3, float v4) + { + r = v1; + g = v2; + b = v3; + a = v4; + return *this; + } + +}; + +struct StreamData +{ + FVector4PalEntry uObjectColor; + FVector4PalEntry uObjectColor2; + FVector4 uDynLightColor; + FVector4PalEntry uAddColor; + FVector4PalEntry uTextureAddColor; + FVector4PalEntry uTextureModulateColor; + FVector4PalEntry uTextureBlendColor; + FVector4PalEntry uFogColor; + float uDesaturationFactor; + float uInterpolationFactor; + float timer; + int useVertexData; + FVector4 uVertexColor; + FVector4 uVertexNormal; + + FVector4 uGlowTopPlane; + FVector4 uGlowTopColor; + FVector4 uGlowBottomPlane; + FVector4 uGlowBottomColor; + + FVector4 uGradientTopPlane; + FVector4 uGradientBottomPlane; + + FVector4 uSplitTopPlane; + FVector4 uSplitBottomPlane; + + FVector4 uDetailParms; +}; + +class FRenderState +{ +protected: + uint8_t mFogEnabled; + uint8_t mTextureEnabled:1; + uint8_t mGlowEnabled : 1; + uint8_t mGradientEnabled : 1; + uint8_t mModelMatrixEnabled : 1; + uint8_t mTextureMatrixEnabled : 1; + uint8_t mSplitEnabled : 1; + uint8_t mBrightmapEnabled : 1; + + int mLightIndex; + int mSpecialEffect; + int mTextureMode; + int mTextureModeFlags; + int mSoftLight; + float mLightParms[4]; + + float mAlphaThreshold; + float mClipSplit[2]; + + StreamData mStreamData = {}; + PalEntry mFogColor; + + FRenderStyle mRenderStyle; + + FMaterialState mMaterial; + FDepthBiasState mBias; + + IVertexBuffer *mVertexBuffer; + int mVertexOffsets[2]; // one per binding point + IIndexBuffer *mIndexBuffer; + + EPassType mPassType = NORMAL_PASS; + +public: + + uint64_t firstFrame = 0; + VSMatrix mModelMatrix; + VSMatrix mTextureMatrix; + +public: + + void Reset() + { + mTextureEnabled = true; + mBrightmapEnabled = mGradientEnabled = mFogEnabled = mGlowEnabled = false; + mFogColor = 0xffffffff; + mStreamData.uFogColor = mFogColor; + mTextureMode = -1; + mTextureModeFlags = 0; + mStreamData.uDesaturationFactor = 0.0f; + mAlphaThreshold = 0.5f; + mModelMatrixEnabled = false; + mTextureMatrixEnabled = false; + mSplitEnabled = false; + mStreamData.uAddColor = 0; + mStreamData.uObjectColor = 0xffffffff; + mStreamData.uObjectColor2 = 0; + mStreamData.uTextureBlendColor = 0; + mStreamData.uTextureAddColor = 0; + mStreamData.uTextureModulateColor = 0; + mSoftLight = 0; + mLightParms[0] = mLightParms[1] = mLightParms[2] = 0.0f; + mLightParms[3] = -1.f; + mSpecialEffect = EFF_NONE; + mLightIndex = -1; + mStreamData.uInterpolationFactor = 0; + mRenderStyle = DefaultRenderStyle(); + mMaterial.Reset(); + mBias.Reset(); + mPassType = NORMAL_PASS; + + mVertexBuffer = nullptr; + mVertexOffsets[0] = mVertexOffsets[1] = 0; + mIndexBuffer = nullptr; + + mStreamData.uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f }; + mStreamData.uGlowTopColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uGlowBottomColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uGlowTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uGlowBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uGradientTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uGradientBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f }; + + mModelMatrix.loadIdentity(); + mTextureMatrix.loadIdentity(); + ClearClipSplit(); + } + + void SetNormal(FVector3 norm) + { + mStreamData.uVertexNormal = { norm.X, norm.Y, norm.Z, 0.f }; + } + + void SetNormal(float x, float y, float z) + { + mStreamData.uVertexNormal = { x, y, z, 0.f }; + } + + void SetColor(float r, float g, float b, float a = 1.f, int desat = 0) + { + mStreamData.uVertexColor = { r, g, b, a }; + mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f); + } + + void SetColor(PalEntry pe, int desat = 0) + { + const float scale = 1.0f / 255.0f; + mStreamData.uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, pe.a * scale }; + mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f); + } + + void SetColorAlpha(PalEntry pe, float alpha = 1.f, int desat = 0) + { + const float scale = 1.0f / 255.0f; + mStreamData.uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, alpha }; + mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f); + } + + void ResetColor() + { + mStreamData.uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f }; + mStreamData.uDesaturationFactor = 0.0f; + } + + void SetTextureMode(int mode) + { + mTextureMode = mode; + } + + void SetTextureMode(FRenderStyle style) + { + if (style.Flags & STYLEF_RedIsAlpha) + { + SetTextureMode(TM_ALPHATEXTURE); + } + else if (style.Flags & STYLEF_ColorIsFixed) + { + SetTextureMode(TM_STENCIL); + } + else if (style.Flags & STYLEF_InvertSource) + { + SetTextureMode(TM_INVERSE); + } + } + + int GetTextureMode() + { + return mTextureMode; + } + + void EnableTexture(bool on) + { + mTextureEnabled = on; + } + + void EnableFog(uint8_t on) + { + mFogEnabled = on; + } + + void SetEffect(int eff) + { + mSpecialEffect = eff; + } + + void EnableGlow(bool on) + { + if (mGlowEnabled && !on) + { + mStreamData.uGlowTopColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uGlowBottomColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + } + mGlowEnabled = on; + } + + void EnableGradient(bool on) + { + mGradientEnabled = on; + } + + void EnableBrightmap(bool on) + { + mBrightmapEnabled = on; + } + + void EnableSplit(bool on) + { + if (mSplitEnabled && !on) + { + mStreamData.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + mStreamData.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + } + mSplitEnabled = on; + } + + void EnableModelMatrix(bool on) + { + mModelMatrixEnabled = on; + } + + void EnableTextureMatrix(bool on) + { + mTextureMatrixEnabled = on; + } + + void SetGlowParams(float *t, float *b) + { + mStreamData.uGlowTopColor = { t[0], t[1], t[2], t[3] }; + mStreamData.uGlowBottomColor = { b[0], b[1], b[2], b[3] }; + } + + void SetSoftLightLevel(int llevel, int blendfactor = 0) + { + if (blendfactor == 0) mLightParms[3] = llevel / 255.f; + else mLightParms[3] = -1.f; + } + + void SetNoSoftLightLevel() + { + mLightParms[3] = -1.f; + } + + void SetGlowPlanes(const FVector4 &tp, const FVector4& bp) + { + mStreamData.uGlowTopPlane = tp; + mStreamData.uGlowBottomPlane = bp; + } + + void SetGradientPlanes(const FVector4& tp, const FVector4& bp) + { + mStreamData.uGradientTopPlane = tp; + mStreamData.uGradientBottomPlane = bp; + } + + void SetSplitPlanes(const FVector4& tp, const FVector4& bp) + { + mStreamData.uSplitTopPlane = tp; + mStreamData.uSplitBottomPlane = bp; + } + + void SetDetailParms(float xscale, float yscale, float bias) + { + mStreamData.uDetailParms = { xscale, yscale, bias, 0 }; + } + + void SetDynLight(float r, float g, float b) + { + mStreamData.uDynLightColor = { r, g, b, 0.0f }; + } + + void SetObjectColor(PalEntry pe) + { + mStreamData.uObjectColor = pe; + } + + void SetObjectColor2(PalEntry pe) + { + mStreamData.uObjectColor2 = pe; + } + + void SetAddColor(PalEntry pe) + { + mStreamData.uAddColor = pe; + } + + void ApplyTextureManipulation(TextureManipulation* texfx) + { + if (!texfx || texfx->AddColor.a == 0) + { + mStreamData.uTextureAddColor.a = 0; // we only need to set the flags to 0 + } + else + { + // set up the whole thing + mStreamData.uTextureAddColor.SetIA(texfx->AddColor); + auto pe = texfx->ModulateColor; + mStreamData.uTextureModulateColor.SetFlt(pe.r * pe.a / 255.f, pe.g * pe.a / 255.f, pe.b * pe.a / 255.f, texfx->DesaturationFactor); + mStreamData.uTextureBlendColor = texfx->BlendColor; + } + } + + void SetFog(PalEntry c, float d) + { + const float LOG2E = 1.442692f; // = 1/log(2) + mFogColor = c; + mStreamData.uFogColor = mFogColor; + if (d >= 0.0f) mLightParms[2] = d * (-LOG2E / 64000.f); + } + + void SetLightParms(float f, float d) + { + mLightParms[1] = f; + mLightParms[0] = d; + } + + PalEntry GetFogColor() const + { + return mFogColor; + } + + void AlphaFunc(int func, float thresh) + { + if (func == Alpha_Greater) mAlphaThreshold = thresh; + else mAlphaThreshold = thresh - 0.001f; + } + + void SetLightIndex(int index) + { + mLightIndex = index; + } + + void SetRenderStyle(FRenderStyle rs) + { + mRenderStyle = rs; + } + + void SetRenderStyle(ERenderStyle rs) + { + mRenderStyle = rs; + } + + void SetDepthBias(float a, float b) + { + mBias.mFactor = a; + mBias.mUnits = b; + mBias.mChanged = true; + } + + void ClearDepthBias() + { + mBias.mFactor = 0; + mBias.mUnits = 0; + mBias.mChanged = true; + } + + void SetMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader) + { + mMaterial.mMaterial = mat; + mMaterial.mClampMode = clampmode; + mMaterial.mTranslation = translation; + mMaterial.mOverrideShader = overrideshader; + mMaterial.mChanged = true; + mTextureModeFlags = mat->GetLayerFlags(); + } + + void SetMaterial(FGameTexture* tex, EUpscaleFlags upscalemask, int scaleflags, int clampmode, int translation, int overrideshader) + { + if (shouldUpscale(tex, upscalemask)) scaleflags |= CTF_Upscale; + SetMaterial(FMaterial::ValidateTexture(tex, scaleflags), clampmode, translation, overrideshader); + } + + void SetClipSplit(float bottom, float top) + { + mClipSplit[0] = bottom; + mClipSplit[1] = top; + } + + void SetClipSplit(float *vals) + { + memcpy(mClipSplit, vals, 2 * sizeof(float)); + } + + void GetClipSplit(float *out) + { + memcpy(out, mClipSplit, 2 * sizeof(float)); + } + + void ClearClipSplit() + { + mClipSplit[0] = -1000000.f; + mClipSplit[1] = 1000000.f; + } + + void SetVertexBuffer(IVertexBuffer *vb, int offset0, int offset1) + { + assert(vb); + mVertexBuffer = vb; + mVertexOffsets[0] = offset0; + mVertexOffsets[1] = offset1; + } + + void SetIndexBuffer(IIndexBuffer *ib) + { + mIndexBuffer = ib; + } + + template void SetVertexBuffer(T *buffer) + { + auto ptrs = buffer->GetBufferObjects(); + SetVertexBuffer(ptrs.first, 0, 0); + SetIndexBuffer(ptrs.second); + } + + void SetInterpolationFactor(float fac) + { + mStreamData.uInterpolationFactor = fac; + } + + float GetInterpolationFactor() + { + return mStreamData.uInterpolationFactor; + } + + void EnableDrawBufferAttachments(bool on) // Used by fog boundary drawer + { + EnableDrawBuffers(on ? GetPassDrawBufferCount() : 1); + } + + int GetPassDrawBufferCount() + { + return mPassType == GBUFFER_PASS ? 3 : 1; + } + + void SetPassType(EPassType passType) + { + mPassType = passType; + } + + EPassType GetPassType() + { + return mPassType; + } + + // API-dependent render interface + + // Draw commands + virtual void ClearScreen() = 0; + virtual void Draw(int dt, int index, int count, bool apply = true) = 0; + virtual void DrawIndexed(int dt, int index, int count, bool apply = true) = 0; + + // Immediate render state change commands. These only change infrequently and should not clutter the render state. + virtual bool SetDepthClamp(bool on) = 0; // Deactivated only by skyboxes. + virtual void SetDepthMask(bool on) = 0; // Used by decals and indirectly by portal setup. + virtual void SetDepthFunc(int func) = 0; // Used by models, portals and mirror surfaces. + virtual void SetDepthRange(float min, float max) = 0; // Used by portal setup. + virtual void SetColorMask(bool r, bool g, bool b, bool a) = 0; // Used by portals. + virtual void SetStencil(int offs, int op, int flags=-1) = 0; // Used by portal setup and render hacks. + virtual void SetCulling(int mode) = 0; // Used by model drawer only. + virtual void EnableClipDistance(int num, bool state) = 0; // Use by sprite sorter for vertical splits. + virtual void Clear(int targets) = 0; // not used during normal rendering + virtual void EnableStencil(bool on) = 0; // always on for 3D, always off for 2D + virtual void SetScissor(int x, int y, int w, int h) = 0; // constant for 3D, changes for 2D + virtual void SetViewport(int x, int y, int w, int h) = 0; // constant for all 3D and all 2D + virtual void EnableDepthTest(bool on) = 0; // used by 2D, portals and render hacks. + virtual void EnableMultisampling(bool on) = 0; // only active for 2D + virtual void EnableLineSmooth(bool on) = 0; // constant setting for each 2D drawer operation + virtual void EnableDrawBuffers(int count, bool apply = false) = 0; // Used by SSAO and EnableDrawBufferAttachments + + void SetColorMask(bool on) + { + SetColorMask(on, on, on, on); + } + +}; + diff --git a/source/core/rendering/hwrenderer/data/renderqueue.h b/source/common/rendering/hwrenderer/data/renderqueue.h similarity index 100% rename from source/core/rendering/hwrenderer/data/renderqueue.h rename to source/common/rendering/hwrenderer/data/renderqueue.h diff --git a/source/core/rendering/hwrenderer/data/shaderuniforms.h b/source/common/rendering/hwrenderer/data/shaderuniforms.h similarity index 100% rename from source/core/rendering/hwrenderer/data/shaderuniforms.h rename to source/common/rendering/hwrenderer/data/shaderuniforms.h diff --git a/source/core/rendering/hwrenderer/postprocessing/hw_postprocess.cpp b/source/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp similarity index 71% rename from source/core/rendering/hwrenderer/postprocessing/hw_postprocess.cpp rename to source/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp index 37f000db9..db991145a 100644 --- a/source/core/rendering/hwrenderer/postprocessing/hw_postprocess.cpp +++ b/source/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp @@ -21,19 +21,19 @@ #include "v_video.h" #include "hw_postprocess.h" -#include "gamecvars.h" -#include "stats.h" -#include "imagehelpers.h" #include "hwrenderer/utility/hw_cvars.h" #include "hwrenderer/postprocessing/hw_postprocess_cvars.h" -#include "palutil.h" -#include "palettecontainer.h" -#include "vectors.h" +#include "hwrenderer/postprocessing/hw_postprocessshader.h" #include +#include "texturemanager.h" +#include "templates.h" +#include "stats.h" +#include "colormaps.h" Postprocess hw_postprocess; PPResource *PPResource::First = nullptr; +TArray PostProcessShaders; bool gpuStatActive = false; bool keepGpuStatActive = false; @@ -76,7 +76,7 @@ void PPBloom::UpdateTextures(int width, int height) void PPBloom::RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneHeight, int fixedcm) { // Only bloom things if enabled and no special fixed light mode is active - if (!gl_bloom || sceneWidth <= 0 || sceneHeight <= 0) + if (!gl_bloom || fixedcm != CM_DEFAULT || gl_ssao_debug || sceneWidth <= 0 || sceneHeight <= 0) { return; } @@ -273,7 +273,7 @@ void PPBloom::BlurStep(PPRenderState *renderstate, const BlurUniforms &blurUnifo float PPBloom::ComputeBlurGaussian(float n, float theta) // theta = Blur Amount { - return (float)((1.0f / sqrtf(2 * pi::pif() * theta)) * expf(-(n * n) / (2.0f * theta * theta))); + return (float)((1.0f / sqrtf(2 * (float)M_PI * theta)) * expf(-(n * n) / (2.0f * theta * theta))); } void PPBloom::ComputeBlurSamples(int sampleCount, float blurAmount, float *sampleWeights) @@ -327,9 +327,9 @@ void PPLensDistort::Render(PPRenderState *renderstate) // Scale factor to keep sampling within the input texture float r2 = aspect * aspect * 0.25f + 0.25f; float sqrt_r2 = sqrt(r2); - float f0 = 1.0f + std::max(r2 * (k[0] + kcube[0] * sqrt_r2), 0.0f); - float f2 = 1.0f + std::max(r2 * (k[2] + kcube[2] * sqrt_r2), 0.0f); - float f = std::max(f0, f2); + float f0 = 1.0f + MAX(r2 * (k[0] + kcube[0] * sqrt_r2), 0.0f); + float f2 = 1.0f + MAX(r2 * (k[2] + kcube[2] * sqrt_r2), 0.0f); + float f = MAX(f0, f2); float scale = 1.0f / f; LensUniforms uniforms; @@ -395,8 +395,8 @@ void PPFXAA::CreateShaders() if (LastQuality == gl_fxaa) return; - FXAALuma = { "engine/shaders/pp/fxaa.fp", "#define FXAA_LUMA_PASS\n", {} }; - FXAA = { "engine/shaders/pp/fxaa.fp", GetDefines(), FXAAUniforms::Desc(), GetMaxVersion() }; + FXAALuma = { "shaders/glsl/fxaa.fp", "#define FXAA_LUMA_PASS\n", {} }; + FXAA = { "shaders/glsl/fxaa.fp", GetDefines(), FXAAUniforms::Desc(), GetMaxVersion() }; LastQuality = gl_fxaa; } @@ -499,8 +499,8 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc void PPCameraExposure::UpdateTextures(int width, int height) { - int firstwidth = std::max(width / 2, 1); - int firstheight = std::max(height / 2, 1); + int firstwidth = MAX(width / 2, 1); + int firstheight = MAX(height / 2, 1); if (ExposureLevels.size() > 0 && ExposureLevels[0].Viewport.width == firstwidth && ExposureLevels[0].Viewport.height == firstheight) { @@ -512,8 +512,8 @@ void PPCameraExposure::UpdateTextures(int width, int height) int i = 0; do { - width = std::max(width / 2, 1); - height = std::max(height / 2, 1); + width = MAX(width / 2, 1); + height = MAX(height / 2, 1); PPExposureLevel blevel; blevel.Viewport.left = 0; @@ -532,6 +532,37 @@ void PPCameraExposure::UpdateTextures(int width, int height) ///////////////////////////////////////////////////////////////////////////// +void PPColormap::Render(PPRenderState *renderstate, int fixedcm) +{ + if (fixedcm < CM_FIRSTSPECIALCOLORMAP || fixedcm >= CM_MAXCOLORMAP) + { + return; + } + + FSpecialColormap *scm = &SpecialColormaps[fixedcm - CM_FIRSTSPECIALCOLORMAP]; + float m[] = { scm->ColorizeEnd[0] - scm->ColorizeStart[0], + scm->ColorizeEnd[1] - scm->ColorizeStart[1], scm->ColorizeEnd[2] - scm->ColorizeStart[2], 0.f }; + + ColormapUniforms uniforms; + uniforms.MapStart = { scm->ColorizeStart[0], scm->ColorizeStart[1], scm->ColorizeStart[2], 0.f }; + uniforms.MapRange = m; + + renderstate->PushGroup("colormap"); + + renderstate->Clear(); + renderstate->Shader = &Colormap; + renderstate->Uniforms.Set(uniforms); + renderstate->Viewport = screen->mScreenViewport; + renderstate->SetInputCurrent(0); + renderstate->SetOutputNext(); + renderstate->SetNoBlend(); + renderstate->Draw(); + + renderstate->PopGroup(); +} + +///////////////////////////////////////////////////////////////////////////// + void PPTonemap::UpdateTextures() { if (gl_tonemap == Palette && !PaletteTexture.Data) @@ -545,7 +576,7 @@ void PPTonemap::UpdateTextures() { for (int b = 0; b < 64; b++) { - PalEntry color = GPalette.BaseColors[(uint8_t)PTM_BestColor((uint32_t*)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4), + PalEntry color = GPalette.BaseColors[(uint8_t)PTM_BestColor((uint32_t *)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4), gl_paltonemap_reverselookup, gl_paltonemap_powtable, 0, 256)]; int index = ((r * 64 + g) * 64 + b) * 4; lut[index] = color.r; @@ -611,7 +642,7 @@ PPAmbientOcclusion::PPAmbientOcclusion() for (int i = 0; i < 16; i++) { - double angle = 2.0 * pi::pi() * distribution(generator) / numDirections[quality]; + double angle = 2.0 * M_PI * distribution(generator) / numDirections[quality]; double x = cos(angle); double y = sin(angle); double z = distribution(generator); @@ -650,14 +681,14 @@ void PPAmbientOcclusion::CreateShaders() #define NUM_STEPS %d.0 )", numDirections, numSteps); - LinearDepth = { "engine/shaders/pp/lineardepth.fp", "", LinearDepthUniforms::Desc() }; - LinearDepthMS = { "engine/shaders/pp/lineardepth.fp", "#define MULTISAMPLE\n", LinearDepthUniforms::Desc() }; - AmbientOcclude = { "engine/shaders/pp/ssao.fp", defines, SSAOUniforms::Desc() }; - AmbientOccludeMS = { "engine/shaders/pp/ssao.fp", defines + "\n#define MULTISAMPLE\n", SSAOUniforms::Desc() }; - BlurVertical = { "engine/shaders/pp/depthblur.fp", "#define BLUR_VERTICAL\n", DepthBlurUniforms::Desc() }; - BlurHorizontal = { "engine/shaders/pp/depthblur.fp", "#define BLUR_HORIZONTAL\n", DepthBlurUniforms::Desc() }; - Combine = { "engine/shaders/pp/ssaocombine.fp", "", AmbientCombineUniforms::Desc() }; - CombineMS = { "engine/shaders/pp/ssaocombine.fp", "#define MULTISAMPLE\n", AmbientCombineUniforms::Desc() }; + LinearDepth = { "shaders/glsl/lineardepth.fp", "", LinearDepthUniforms::Desc() }; + LinearDepthMS = { "shaders/glsl/lineardepth.fp", "#define MULTISAMPLE\n", LinearDepthUniforms::Desc() }; + AmbientOcclude = { "shaders/glsl/ssao.fp", defines, SSAOUniforms::Desc() }; + AmbientOccludeMS = { "shaders/glsl/ssao.fp", defines + "\n#define MULTISAMPLE\n", SSAOUniforms::Desc() }; + BlurVertical = { "shaders/glsl/depthblur.fp", "#define BLUR_VERTICAL\n", DepthBlurUniforms::Desc() }; + BlurHorizontal = { "shaders/glsl/depthblur.fp", "#define BLUR_HORIZONTAL\n", DepthBlurUniforms::Desc() }; + Combine = { "shaders/glsl/ssaocombine.fp", "", AmbientCombineUniforms::Desc() }; + CombineMS = { "shaders/glsl/ssaocombine.fp", "#define MULTISAMPLE\n", AmbientCombineUniforms::Desc() }; LastQuality = gl_ssao; } @@ -710,7 +741,7 @@ void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneW LinearDepthUniforms linearUniforms; linearUniforms.SampleIndex = 0; linearUniforms.LinearizeDepthA = 1.0f / screen->GetZFar() - 1.0f / screen->GetZNear(); - linearUniforms.LinearizeDepthB = std::max(1.0f / screen->GetZNear(), 1.e-8f); + linearUniforms.LinearizeDepthB = MAX(1.0f / screen->GetZNear(), 1.e-8f); linearUniforms.InverseDepthRangeA = 1.0f; linearUniforms.InverseDepthRangeB = 0.0f; linearUniforms.Scale = sceneScale; @@ -833,17 +864,243 @@ PPPresent::PPPresent() Dither = { 8, 8, PixelFormat::R32f, pixels }; } +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// + +CVAR(Bool, gl_custompost, true, 0) + +void PPCustomShaders::Run(PPRenderState *renderstate, FString target) +{ + if (!gl_custompost) + return; + + CreateShaders(); + + for (auto &shader : mShaders) + { + if (shader->Desc->Target == target && shader->Desc->Enabled) + { + shader->Run(renderstate); + } + } +} + +void PPCustomShaders::CreateShaders() +{ + if (mShaders.size() == PostProcessShaders.Size()) + return; + + mShaders.clear(); + + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + mShaders.push_back(std::make_unique(&PostProcessShaders[i])); + } +} + +///////////////////////////////////////////////////////////////////////////// + +PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(desc) +{ + // Build an uniform block to be used as input + TMap::Iterator it(Desc->Uniforms); + TMap::Pair *pair; + size_t offset = 0; + while (it.NextPair(pair)) + { + FString type; + FString name = pair->Key; + + switch (pair->Value.Type) + { + case PostProcessUniformType::Float: AddUniformField(offset, name, UniformType::Float, sizeof(float)); break; + case PostProcessUniformType::Int: AddUniformField(offset, name, UniformType::Int, sizeof(int)); break; + case PostProcessUniformType::Vec2: AddUniformField(offset, name, UniformType::Vec2, sizeof(float) * 2); break; + case PostProcessUniformType::Vec3: AddUniformField(offset, name, UniformType::Vec3, sizeof(float) * 3, sizeof(float) * 4); break; + default: break; + } + } + UniformStructSize = ((int)offset + 15) / 16 * 16; + + // Build the input textures + FString uniformTextures; + uniformTextures += "layout(binding=0) uniform sampler2D InputTexture;\n"; + + TMap::Iterator itTextures(Desc->Textures); + TMap::Pair *pairTextures; + int binding = 1; + while (itTextures.NextPair(pairTextures)) + { + uniformTextures.AppendFormat("layout(binding=%d) uniform sampler2D %s;\n", binding++, pairTextures->Key.GetChars()); + } + + // Setup pipeline + FString pipelineInOut; + if (screen->IsVulkan()) + { + pipelineInOut += "layout(location=0) in vec2 TexCoord;\n"; + pipelineInOut += "layout(location=0) out vec4 FragColor;\n"; + } + else + { + pipelineInOut += "in vec2 TexCoord;\n"; + pipelineInOut += "out vec4 FragColor;\n"; + } + + FString prolog; + prolog += uniformTextures; + prolog += pipelineInOut; + + Shader = PPShader(Desc->ShaderLumpName, prolog, Fields); +} + +void PPCustomShaderInstance::Run(PPRenderState *renderstate) +{ + renderstate->PushGroup(Desc->Name); + + renderstate->Clear(); + renderstate->Shader = &Shader; + renderstate->Viewport = screen->mScreenViewport; + renderstate->SetNoBlend(); + renderstate->SetOutputNext(); + //renderstate->SetDebugName(Desc->ShaderLumpName.GetChars()); + + SetTextures(renderstate); + SetUniforms(renderstate); + + renderstate->Draw(); + + renderstate->PopGroup(); +} + +void PPCustomShaderInstance::SetTextures(PPRenderState *renderstate) +{ + renderstate->SetInputCurrent(0, PPFilterMode::Linear); + + int textureIndex = 1; + TMap::Iterator it(Desc->Textures); + TMap::Pair *pair; + while (it.NextPair(pair)) + { + FString name = pair->Value; + auto gtex = TexMan.GetGameTexture(TexMan.CheckForTexture(name, ETextureType::Any), true); + if (gtex && gtex->isValid()) + { + // Why does this completely circumvent the normal way of handling textures? + // This absolutely needs fixing because it will also circumvent any potential caching system that may get implemented. + // + // To do: fix the above problem by adding PPRenderState::SetInput(FTexture *tex) + + auto tex = gtex->GetTexture(); + auto &pptex = Textures[tex]; + if (!pptex) + { + auto buffer = tex->CreateTexBuffer(0); + + std::shared_ptr data(new uint32_t[buffer.mWidth * buffer.mHeight], [](void *p) { delete[](uint32_t*)p; }); + + int count = buffer.mWidth * buffer.mHeight; + uint8_t *pixels = (uint8_t *)data.get(); + for (int i = 0; i < count; i++) + { + int pos = i << 2; + pixels[pos] = buffer.mBuffer[pos + 2]; + pixels[pos + 1] = buffer.mBuffer[pos + 1]; + pixels[pos + 2] = buffer.mBuffer[pos]; + pixels[pos + 3] = buffer.mBuffer[pos + 3]; + } + + pptex = std::make_unique(buffer.mWidth, buffer.mHeight, PixelFormat::Rgba8, data); + } + + renderstate->SetInputTexture(textureIndex, pptex.get(), PPFilterMode::Linear, PPWrapMode::Repeat); + textureIndex++; + } + } +} + +void PPCustomShaderInstance::SetUniforms(PPRenderState *renderstate) +{ + TArray uniforms; + uniforms.Resize(UniformStructSize); + + TMap::Iterator it(Desc->Uniforms); + TMap::Pair *pair; + while (it.NextPair(pair)) + { + auto it2 = FieldOffset.find(pair->Key); + if (it2 != FieldOffset.end()) + { + uint8_t *dst = &uniforms[it2->second]; + float fValues[4]; + int iValues[4]; + switch (pair->Value.Type) + { + case PostProcessUniformType::Float: + fValues[0] = (float)pair->Value.Values[0]; + memcpy(dst, fValues, sizeof(float)); + break; + case PostProcessUniformType::Int: + iValues[0] = (int)pair->Value.Values[0]; + memcpy(dst, iValues, sizeof(int)); + break; + case PostProcessUniformType::Vec2: + fValues[0] = (float)pair->Value.Values[0]; + fValues[1] = (float)pair->Value.Values[1]; + memcpy(dst, fValues, sizeof(float) * 2); + break; + case PostProcessUniformType::Vec3: + fValues[0] = (float)pair->Value.Values[0]; + fValues[1] = (float)pair->Value.Values[1]; + fValues[2] = (float)pair->Value.Values[2]; + memcpy(dst, fValues, sizeof(float) * 3); + break; + default: + break; + } + } + } + + renderstate->Uniforms.Data = uniforms; +} + +void PPCustomShaderInstance::AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize, size_t alignment) +{ + if (alignment == 0) alignment = fieldsize; + offset = (offset + alignment - 1) / alignment * alignment; + + FieldOffset[name] = offset; + + auto name2 = std::make_unique(name); + auto chars = name2->GetChars(); + FieldNames.push_back(std::move(name2)); + Fields.push_back({ chars, type, offset }); + offset += fieldsize; + + if (fieldsize != alignment) // Workaround for buggy OpenGL drivers that does not do std140 layout correctly for vec3 + { + name2 = std::make_unique(name + "_F39350FF12DE_padding"); + chars = name2->GetChars(); + FieldNames.push_back(std::move(name2)); + Fields.push_back({ chars, UniformType::Float, offset }); + offset += alignment - fieldsize; + } +} void Postprocess::Pass1(PPRenderState* state, int fixedcm, int sceneWidth, int sceneHeight) { exposure.Render(state, sceneWidth, sceneHeight); + customShaders.Run(state, "beforebloom"); bloom.RenderBloom(state, sceneWidth, sceneHeight, fixedcm); } void Postprocess::Pass2(PPRenderState* state, int fixedcm, int sceneWidth, int sceneHeight) { tonemap.Render(state); + colormap.Render(state, fixedcm); lens.Render(state); fxaa.Render(state); + customShaders.Run(state, "scene"); } diff --git a/source/core/rendering/hwrenderer/postprocessing/hw_postprocess.h b/source/common/rendering/hwrenderer/postprocessing/hw_postprocess.h similarity index 84% rename from source/core/rendering/hwrenderer/postprocessing/hw_postprocess.h rename to source/common/rendering/hwrenderer/postprocessing/hw_postprocess.h index ea89175db..8c74af83e 100644 --- a/source/core/rendering/hwrenderer/postprocessing/hw_postprocess.h +++ b/source/common/rendering/hwrenderer/postprocessing/hw_postprocess.h @@ -303,7 +303,7 @@ public: void ResetBackend() override { Backend.reset(); } - FString VertexShader = "engine/shaders/pp/screenquad.vp"; + FString VertexShader = "shaders/glsl/screenquad.vp"; FString FragmentShader; FString Defines; std::vector Uniforms; @@ -376,10 +376,10 @@ private: int lastWidth = 0; int lastHeight = 0; - PPShader BloomCombine = { "engine/shaders/pp/bloomcombine.fp", "", {} }; - PPShader BloomExtract = { "engine/shaders/pp/bloomextract.fp", "", ExtractUniforms::Desc() }; - PPShader BlurVertical = { "engine/shaders/pp/blur.fp", "#define BLUR_VERTICAL\n", BlurUniforms::Desc() }; - PPShader BlurHorizontal = { "engine/shaders/pp/blur.fp", "#define BLUR_HORIZONTAL\n", BlurUniforms::Desc() }; + PPShader BloomCombine = { "shaders/glsl/bloomcombine.fp", "", {} }; + PPShader BloomExtract = { "shaders/glsl/bloomextract.fp", "", ExtractUniforms::Desc() }; + PPShader BlurVertical = { "shaders/glsl/blur.fp", "#define BLUR_VERTICAL\n", BlurUniforms::Desc() }; + PPShader BlurHorizontal = { "shaders/glsl/blur.fp", "#define BLUR_HORIZONTAL\n", BlurUniforms::Desc() }; }; ///////////////////////////////////////////////////////////////////////////// @@ -412,7 +412,7 @@ public: void Render(PPRenderState *renderstate); private: - PPShader Lens = { "engine/shaders/pp/lensdistortion.fp", "", LensUniforms::Desc() }; + PPShader Lens = { "shaders/glsl/lensdistortion.fp", "", LensUniforms::Desc() }; }; ///////////////////////////////////////////////////////////////////////////// @@ -504,9 +504,9 @@ private: std::vector ExposureLevels; bool FirstExposureFrame = true; - PPShader ExposureExtract = { "engine/shaders/pp/exposureextract.fp", "", ExposureExtractUniforms::Desc() }; - PPShader ExposureAverage = { "engine/shaders/pp/exposureaverage.fp", "", {}, 400 }; - PPShader ExposureCombine = { "engine/shaders/pp/exposurecombine.fp", "", ExposureCombineUniforms::Desc() }; + PPShader ExposureExtract = { "shaders/glsl/exposureextract.fp", "", ExposureExtractUniforms::Desc() }; + PPShader ExposureAverage = { "shaders/glsl/exposureaverage.fp", "", {}, 400 }; + PPShader ExposureCombine = { "shaders/glsl/exposurecombine.fp", "", ExposureCombineUniforms::Desc() }; }; ///////////////////////////////////////////////////////////////////////////// @@ -526,6 +526,15 @@ struct ColormapUniforms } }; +class PPColormap +{ +public: + void Render(PPRenderState *renderstate, int fixedcm); + +private: + PPShader Colormap = { "shaders/glsl/colormap.fp", "", ColormapUniforms::Desc() }; +}; + ///////////////////////////////////////////////////////////////////////////// class PPTonemap @@ -539,11 +548,11 @@ private: PPTexture PaletteTexture; - PPShader LinearShader = { "engine/shaders/pp/tonemap.fp", "#define LINEAR\n", {} }; - PPShader ReinhardShader = { "engine/shaders/pp/tonemap.fp", "#define REINHARD\n", {} }; - PPShader HejlDawsonShader = { "engine/shaders/pp/tonemap.fp", "#define HEJLDAWSON\n", {} }; - PPShader Uncharted2Shader = { "engine/shaders/pp/tonemap.fp", "#define UNCHARTED2\n", {} }; - PPShader PaletteShader = { "engine/shaders/pp/tonemap.fp", "#define PALETTE\n", {} }; + PPShader LinearShader = { "shaders/glsl/tonemap.fp", "#define LINEAR\n", {} }; + PPShader ReinhardShader = { "shaders/glsl/tonemap.fp", "#define REINHARD\n", {} }; + PPShader HejlDawsonShader = { "shaders/glsl/tonemap.fp", "#define HEJLDAWSON\n", {} }; + PPShader Uncharted2Shader = { "shaders/glsl/tonemap.fp", "#define UNCHARTED2\n", {} }; + PPShader PaletteShader = { "shaders/glsl/tonemap.fp", "#define PALETTE\n", {} }; enum TonemapMode { @@ -744,10 +753,70 @@ public: PPTexture Dither; - PPShader Present = { "engine/shaders/pp/present.fp", "", PresentUniforms::Desc() }; - PPShader Checker3D = { "engine/shaders/pp/present_checker3d.fp", "", PresentUniforms::Desc() }; - PPShader Column3D = { "engine/shaders/pp/present_column3d.fp", "", PresentUniforms::Desc() }; - PPShader Row3D = { "engine/shaders/pp/present_row3d.fp", "", PresentUniforms::Desc() }; + PPShader Present = { "shaders/glsl/present.fp", "", PresentUniforms::Desc() }; + PPShader Checker3D = { "shaders/glsl/present_checker3d.fp", "", PresentUniforms::Desc() }; + PPShader Column3D = { "shaders/glsl/present_column3d.fp", "", PresentUniforms::Desc() }; + PPShader Row3D = { "shaders/glsl/present_row3d.fp", "", PresentUniforms::Desc() }; +}; + +struct ShadowMapUniforms +{ + float ShadowmapQuality; + int NodesCount; + float Padding0, Padding1; + + static std::vector Desc() + { + return + { + { "ShadowmapQuality", UniformType::Float, offsetof(ShadowMapUniforms, ShadowmapQuality) }, + { "NodesCount", UniformType::Int, offsetof(ShadowMapUniforms, NodesCount) }, + { "Padding0", UniformType::Float, offsetof(ShadowMapUniforms, Padding0) }, + { "Padding1", UniformType::Float, offsetof(ShadowMapUniforms, Padding1) }, + }; + } +}; + +class PPShadowMap +{ +public: + void Update(PPRenderState *renderstate); + +private: + PPShader ShadowMap = { "shaders/glsl/shadowmap.fp", "", ShadowMapUniforms::Desc() }; +}; + +class PPCustomShaderInstance +{ +public: + PPCustomShaderInstance(PostProcessShader *desc); + + void Run(PPRenderState *renderstate); + + PostProcessShader *Desc = nullptr; + +private: + void AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize, size_t alignment = 0); + void SetTextures(PPRenderState *renderstate); + void SetUniforms(PPRenderState *renderstate); + + PPShader Shader; + int UniformStructSize = 0; + std::vector Fields; + std::vector> FieldNames; + std::map> Textures; + std::map FieldOffset; +}; + +class PPCustomShaders +{ +public: + void Run(PPRenderState *renderstate, FString target); + +private: + void CreateShaders(); + + std::vector> mShaders; }; ///////////////////////////////////////////////////////////////////////////// @@ -759,9 +828,12 @@ public: PPLensDistort lens; PPFXAA fxaa; PPCameraExposure exposure; + PPColormap colormap; PPTonemap tonemap; PPAmbientOcclusion ssao; PPPresent present; + PPShadowMap shadowmap; + PPCustomShaders customShaders; void Pass1(PPRenderState *state, int fixedcm, int sceneWidth, int sceneHeight); diff --git a/source/core/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp b/source/common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp similarity index 100% rename from source/core/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp rename to source/common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp diff --git a/source/core/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.h b/source/common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.h similarity index 100% rename from source/core/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.h rename to source/common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.h diff --git a/source/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h b/source/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h new file mode 100644 index 000000000..523b8d8d0 --- /dev/null +++ b/source/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h @@ -0,0 +1,32 @@ +#pragma once + +enum class PostProcessUniformType +{ + Undefined, + Int, + Float, + Vec2, + Vec3 +}; + +struct PostProcessUniformValue +{ + PostProcessUniformType Type = PostProcessUniformType::Undefined; + double Values[4] = { 0.0, 0.0, 0.0, 0.0 }; +}; + +struct PostProcessShader +{ + FString Target; + FString ShaderLumpName; + int ShaderVersion = 0; + + FString Name; + bool Enabled = false; + + TMap Uniforms; + TMap Textures; +}; + +extern TArray PostProcessShaders; + diff --git a/source/common/rendering/i_video.h b/source/common/rendering/i_video.h new file mode 100644 index 000000000..d9a9b9701 --- /dev/null +++ b/source/common/rendering/i_video.h @@ -0,0 +1,38 @@ +#ifndef __I_VIDEO_H__ +#define __I_VIDEO_H__ + +#include + +class DFrameBuffer; + + +class IVideo +{ +public: + virtual ~IVideo() {} + + virtual DFrameBuffer *CreateFrameBuffer() = 0; + + bool SetResolution(); + + virtual void DumpAdapters(); +}; + +void I_InitGraphics(); +void I_ShutdownGraphics(); + +extern IVideo *Video; + +void I_PolyPresentInit(); +uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch); +void I_PolyPresentUnlock(int x, int y, int w, int h); +void I_PolyPresentDeinit(); + + +// Pause a bit. +// [RH] Despite the name, it apparently never waited for the VBL, even in +// the original DOS version (if the Heretic/Hexen source is any indicator). +void I_WaitVBL(int count); + + +#endif // __I_VIDEO_H__ diff --git a/source/common/rendering/r_videoscale.cpp b/source/common/rendering/r_videoscale.cpp new file mode 100644 index 000000000..236493fb1 --- /dev/null +++ b/source/common/rendering/r_videoscale.cpp @@ -0,0 +1,306 @@ +/*--------------------------------------------------------------------------- +** +** Copyright(C) 2017 Magnus Norddahl +** Copyright(C) 2017-2020 Rachael Alexanderson +** 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 +#include "c_dispatch.h" +#include "c_cvars.h" +#include "v_video.h" +#include "templates.h" +#include "r_videoscale.h" +#include "cmdlib.h" +#include "v_draw.h" +#include "i_interface.h" +#include "printf.h" + +#define NUMSCALEMODES countof(vScaleTable) +extern bool setsizeneeded; + +EXTERN_CVAR(Int, vid_aspect) + +CUSTOM_CVAR(Int, vid_scale_customwidth, VID_MIN_WIDTH, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < VID_MIN_WIDTH) + self = VID_MIN_WIDTH; + setsizeneeded = true; +} +CUSTOM_CVAR(Int, vid_scale_customheight, VID_MIN_HEIGHT, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < VID_MIN_HEIGHT) + self = VID_MIN_HEIGHT; + setsizeneeded = true; +} +CVAR(Bool, vid_scale_linear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Float, vid_scale_custompixelaspect, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + setsizeneeded = true; + if (self < 0.2 || self > 5.0) + self = 1.0; +} + +static const int VID_MIN_UI_WIDTH = 640; +static const int VID_MIN_UI_HEIGHT = 400; + +namespace +{ + uint32_t min_width = VID_MIN_WIDTH; + uint32_t min_height = VID_MIN_HEIGHT; + + float v_MinimumToFill(uint32_t inwidth, uint32_t inheight) + { + // sx = screen x dimension, sy = same for y + float sx = (float)inwidth, sy = (float)inheight; + static float lastsx = 0., lastsy = 0., result = 0.; + if (lastsx != sx || lastsy != sy) + { + if (sx <= 0. || sy <= 0.) + return 1.; // prevent x/0 error + // set absolute minimum scale to fill the entire screen but get as close to 640x400 as possible + float ssx = (float)(VID_MIN_UI_WIDTH) / sx, ssy = (float)(VID_MIN_UI_HEIGHT) / sy; + result = (ssx < ssy) ? ssy : ssx; + lastsx = sx; + lastsy = sy; + } + return result; + } + inline uint32_t v_mfillX(uint32_t inwidth, uint32_t inheight) + { + return (uint32_t)((float)inwidth * v_MinimumToFill(inwidth, inheight)); + } + inline uint32_t v_mfillY(uint32_t inwidth, uint32_t inheight) + { + return (uint32_t)((float)inheight * v_MinimumToFill(inwidth, inheight)); + } + inline void refresh_minimums() + { + // specialUI is tracking a state where high-res console fonts are actually required, and + // aren't actually rendered correctly in 320x200. this forces the game to revert to the 640x400 + // minimum set in GZDoom 4.0.0, but only while those fonts are required. + + static bool lastspecialUI = false; + bool isInActualMenu = false; + + bool specialUI = sysCallbacks && (!sysCallbacks->IsSpecialUI || sysCallbacks->IsSpecialUI()); + + if (specialUI == lastspecialUI) + return; + + lastspecialUI = specialUI; + setsizeneeded = true; + + if (!specialUI) + { + min_width = VID_MIN_WIDTH; + min_height = VID_MIN_HEIGHT; + } + else + { + min_width = VID_MIN_UI_WIDTH; + min_height = VID_MIN_UI_HEIGHT; + } + } + + // the odd formatting of this struct definition is meant to resemble a table header. set your tab stops to 4 when editing this file. + struct v_ScaleTable + { bool isValid; uint32_t(*GetScaledWidth)(uint32_t Width, uint32_t Height); uint32_t(*GetScaledHeight)(uint32_t Width, uint32_t Height); float pixelAspect; bool isCustom; }; + v_ScaleTable vScaleTable[] = + { + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return Width; }, [](uint32_t Width, uint32_t Height)->uint32_t { return Height; }, 1.0f, false }, // 0 - Native + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX(Width, Height); }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY(Width, Height); }, 1.0f, false }, // 6 - Minimum Scale to Fill Entire Screen + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 640; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 400; }, 1.2f, false }, // 2 - 640x400 (formerly 320x200) + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 960; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 600; }, 1.2f, false }, // 3 - 960x600 (formerly 640x400) + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 1280; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 800; }, 1.2f, false }, // 4 - 1280x800 + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customwidth; }, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customheight; }, 1.0f, true }, // 5 - Custom + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 320; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 200; }, 1.2f, false }, // 7 - 320x200 + }; + bool isOutOfBounds(int x) + { + return (x < 0 || x >= int(NUMSCALEMODES) || vScaleTable[x].isValid == false); + } +} + +void R_ShowCurrentScaling(); +CUSTOM_CVAR(Float, vid_scalefactor, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + setsizeneeded = true; + if (self < 0.05 || self > 2.0) + self = 1.0; + if (self != 1.0) + R_ShowCurrentScaling(); +} + +CUSTOM_CVAR(Int, vid_scalemode, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + setsizeneeded = true; + if (isOutOfBounds(self)) + self = 0; +} + +CUSTOM_CVAR(Bool, vid_cropaspect, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + setsizeneeded = true; +} + +bool ViewportLinearScale() +{ + if (isOutOfBounds(vid_scalemode)) + vid_scalemode = 0; + // always use linear if supersampling + int x = screen->GetClientWidth(), y = screen->GetClientHeight(); + float aspectmult = ViewportPixelAspect(); + if (aspectmult > 1.f) + aspectmult = 1.f / aspectmult; + if ((ViewportScaledWidth(x,y) > (x * aspectmult)) || (ViewportScaledHeight(x,y) > (y * aspectmult))) + return true; + + return vid_scale_linear; +} + +int ViewportScaledWidth(int width, int height) +{ + if (isOutOfBounds(vid_scalemode)) + vid_scalemode = 0; + refresh_minimums(); + if (vid_cropaspect && height > 0) + { + width = ((float)width/height > ActiveRatio(width, height)) ? (int)(height * ActiveRatio(width, height)) : width; + height = ((float)width/height < ActiveRatio(width, height)) ? (int)(width / ActiveRatio(width, height)) : height; + } + return (int)std::max((int32_t)min_width, (int32_t)(vid_scalefactor * vScaleTable[vid_scalemode].GetScaledWidth(width, height))); +} + +int ViewportScaledHeight(int width, int height) +{ + if (isOutOfBounds(vid_scalemode)) + vid_scalemode = 0; + if (vid_cropaspect && height > 0) + { + height = ((float)width/height < ActiveRatio(width, height)) ? (int)(width / ActiveRatio(width, height)) : height; + width = ((float)width/height > ActiveRatio(width, height)) ? (int)(height * ActiveRatio(width, height)) : width; + } + return (int)std::max((int32_t)min_height, (int32_t)(vid_scalefactor * vScaleTable[vid_scalemode].GetScaledHeight(width, height))); +} + +float ViewportPixelAspect() +{ + if (isOutOfBounds(vid_scalemode)) + vid_scalemode = 0; + // hack - use custom scaling if in "custom" mode + if (vScaleTable[vid_scalemode].isCustom) + return vid_scale_custompixelaspect; + return vScaleTable[vid_scalemode].pixelAspect; +} + +void R_ShowCurrentScaling() +{ + int x1 = screen->GetClientWidth(), y1 = screen->GetClientHeight(), x2 = ViewportScaledWidth(x1, y1), y2 = ViewportScaledHeight(x1, y1); + Printf("Current vid_scalefactor: %f\n", (float)(vid_scalefactor)); + Printf("Real resolution: %i x %i\nEmulated resolution: %i x %i\n", x1, y1, x2, y2); +} + +CCMD (vid_showcurrentscaling) +{ + R_ShowCurrentScaling(); +} + +CCMD (vid_scaletowidth) +{ + if (argv.argc() > 1) + { + // the following enables the use of ViewportScaledWidth to get the proper dimensions in custom scale modes + vid_scalefactor = 1; + vid_scalefactor = (float)((double)atof(argv[1]) / ViewportScaledWidth(screen->GetClientWidth(), screen->GetClientHeight())); + } +} + +CCMD (vid_scaletoheight) +{ + if (argv.argc() > 1) + { + vid_scalefactor = 1; + vid_scalefactor = (float)((double)atof(argv[1]) / ViewportScaledHeight(screen->GetClientWidth(), screen->GetClientHeight())); + } +} + +inline bool atob(char* I) +{ + if (stricmp (I, "true") == 0 || stricmp (I, "1") == 0) + return true; + return false; +} + +CCMD (vid_setscale) +{ + if (argv.argc() > 2) + { + vid_scale_customwidth = atoi(argv[1]); + vid_scale_customheight = atoi(argv[2]); + if (argv.argc() > 3) + { + vid_scale_linear = atob(argv[3]); + if (argv.argc() > 4) + { + vid_scale_custompixelaspect = (float)atof(argv[4]); + } + } + vid_scalemode = 5; + vid_scalefactor = 1.0; + } + else + { + Printf("Usage: vid_setscale [bool linear] [float pixel-shape]\nThis command will create a custom viewport scaling mode.\n"); + } +} + +CCMD (vid_scaletolowest) +{ + uint32_t method = 0; + if (argv.argc() > 1) + method = atoi(argv[1]); + switch (method) + { + case 1: // Method 1: set a custom video scaling + vid_scalemode = 5; + vid_scalefactor = 1.0; + vid_scale_custompixelaspect = 1.0; + vid_scale_customwidth = v_mfillX(screen->GetClientWidth(), screen->GetClientHeight()); + vid_scale_customheight = v_mfillY(screen->GetClientWidth(), screen->GetClientHeight()); + break; + case 2: // Method 2: use the actual downscaling mode directly + vid_scalemode = 1; + vid_scalefactor = 1.0; + break; + default: // Default method: use vid_scalefactor to achieve the result on a default scaling mode + vid_scalemode = 0; + vid_scalefactor = v_MinimumToFill(screen->GetClientWidth(), screen->GetClientHeight()); + break; + } +} diff --git a/source/common/rendering/r_videoscale.h b/source/common/rendering/r_videoscale.h new file mode 100644 index 000000000..430ad1555 --- /dev/null +++ b/source/common/rendering/r_videoscale.h @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------- +** +** Copyright(C) 2017 Magnus Norddahl +** Copyright(C) 2017-2020 Rachael Alexanderson +** 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. +**--------------------------------------------------------------------------- +** +*/ + +#ifndef __VIDEOSCALE_H__ +#define __VIDEOSCALE_H__ +EXTERN_CVAR (Int, vid_scalemode) +bool ViewportLinearScale(); +int ViewportScaledWidth(int width, int height); +int ViewportScaledHeight(int width, int height); +float ViewportPixelAspect(); +#endif //__VIDEOSCALE_H__ \ No newline at end of file diff --git a/source/core/colormaps.h b/source/core/colormaps.h new file mode 100644 index 000000000..1043199f7 --- /dev/null +++ b/source/core/colormaps.h @@ -0,0 +1,17 @@ +#ifndef __RES_CMAP_H +#define __RES_CMAP_H + +enum EColorManipulation +{ + CM_PLAIN2D = -2, // regular 2D drawing. + CM_INVALID = -1, + CM_DEFAULT = 0, // untranslated + CM_FIRSTSPECIALCOLORMAP, // first special fixed colormap + CM_FIRSTSPECIALCOLORMAPFORCED = 0x08000000, // first special fixed colormap, application forced (for 2D overlays) +}; + +#define CM_MAXCOLORMAP int(CM_FIRSTSPECIALCOLORMAP + SpecialColormaps.Size()) +#define CM_MAXCOLORMAPFORCED int(CM_FIRSTSPECIALCOLORMAPFORCED + SpecialColormaps.Size()) + + +#endif diff --git a/source/core/console/c_console.cpp b/source/core/console/c_console.cpp index 29394d9cf..e2fecc597 100644 --- a/source/core/console/c_console.cpp +++ b/source/core/console/c_console.cpp @@ -1283,7 +1283,7 @@ void C_FullConsole () gamestate = GS_FULLCONSOLE; primaryLevel->Music = ""; S_Start (); - S_StartMusic(); + S_StopMusic(true); P_FreeLevelData (); } else diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index c9ff2457e..4b125f648 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -92,6 +92,7 @@ int myconnectindex, numplayers; int connecthead, connectpoint2[MAXMULTIPLAYERS]; int32_t xres = -1, yres = -1, bpp = 0; auto vsnprintfptr = vsnprintf; // This is an inline in Visual Studio but we need an address for it to satisfy the MinGW compiled libraries. +bool setsizeneeded; MapRecord mapList[512]; // Due to how this gets used it needs to be static. EDuke defines 7 episode plus one spare episode with 64 potential levels each and relies on the static array which is freely accessible by scripts. diff --git a/source/core/rendering/hwrenderer/data/hw_viewpointbuffer.cpp b/source/core/rendering/hwrenderer/data/hw_viewpointbuffer.cpp index 268bd4902..3846a4ccd 100644 --- a/source/core/rendering/hwrenderer/data/hw_viewpointbuffer.cpp +++ b/source/core/rendering/hwrenderer/data/hw_viewpointbuffer.cpp @@ -27,7 +27,6 @@ #include "hwrenderer/data/shaderuniforms.h" #include "hwrenderer/scene/hw_viewpointuniforms.h" -#include "hwrenderer/scene/hw_drawinfo.h" #include "hwrenderer/scene/hw_renderstate.h" #include "hw_viewpointbuffer.h" diff --git a/source/core/rendering/r_videoscale.cpp b/source/core/rendering/r_videoscale.cpp index ef21c8141..4dde60d89 100644 --- a/source/core/rendering/r_videoscale.cpp +++ b/source/core/rendering/r_videoscale.cpp @@ -38,6 +38,7 @@ #include "r_videoscale.h" #include "cmdlib.h" #include "v_draw.h" +#include "i_interface.h" #include "c_console.h" #include "menu/menu.h" @@ -45,12 +46,9 @@ #define NUMSCALEMODES countof(vScaleTable) bool setsizeneeded; -//extern bool generic_ui; EXTERN_CVAR(Int, vid_aspect) -EXTERN_CVAR(Bool, log_vgafont) -EXTERN_CVAR(Bool, dlg_vgafont) CUSTOM_CVAR(Int, vid_scale_customwidth, VID_MIN_WIDTH, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { @@ -72,6 +70,9 @@ CUSTOM_CVAR(Float, vid_scale_custompixelaspect, 1.0, CVAR_ARCHIVE | CVAR_GLOBALC self = 1.0; } +static const int VID_MIN_UI_WIDTH = 640; +static const int VID_MIN_UI_HEIGHT = 400; + namespace { uint32_t min_width = VID_MIN_WIDTH; @@ -87,7 +88,7 @@ namespace if (sx <= 0. || sy <= 0.) return 1.; // prevent x/0 error // set absolute minimum scale to fill the entire screen but get as close to 640x400 as possible - float ssx = (float)(min_width) / sx, ssy = (float)(min_height) / sy; + float ssx = (float)(VID_MIN_UI_WIDTH) / sx, ssy = (float)(VID_MIN_UI_HEIGHT) / sy; result = (ssx < ssy) ? ssy : ssx; lastsx = sx; lastsy = sy; @@ -111,9 +112,7 @@ namespace static bool lastspecialUI = false; bool isInActualMenu = false; -// bool specialUI = (generic_ui || !!log_vgafont || !!dlg_vgafont || ConsoleState != c_up || -// (menuactive == MENU_On && CurrentMenu && !CurrentMenu->IsKindOf("ConversationMenu"))); - bool specialUI = true; + bool specialUI = sysCallbacks && (!sysCallbacks->IsSpecialUI || sysCallbacks->IsSpecialUI()); if (specialUI == lastspecialUI) return; @@ -148,7 +147,7 @@ namespace }; bool isOutOfBounds(int x) { - return (x < 0 || x >= NUMSCALEMODES || vScaleTable[x].isValid == false); + return (x < 0 || x >= int(NUMSCALEMODES) || vScaleTable[x].isValid == false); } } diff --git a/source/core/rendering/v_video.h b/source/core/rendering/v_video.h index 00995509d..4d3c1615b 100644 --- a/source/core/rendering/v_video.h +++ b/source/core/rendering/v_video.h @@ -47,9 +47,6 @@ static const int VID_MIN_WIDTH = 640; static const int VID_MIN_HEIGHT = 400; -static const int VID_MIN_UI_WIDTH = 640; -static const int VID_MIN_UI_HEIGHT = 400; - struct sector_t; struct FPortalSceneState; class FSkyVertexBuffer;