From e754bad17e5770ccbcceb45c39f31d7e8bf6ff58 Mon Sep 17 00:00:00 2001 From: ModMaker101 <119018978+ModMaker101@users.noreply.github.com> Date: Sat, 7 Mar 2026 04:00:38 -0500 Subject: [PATCH] Improve gamma shader parity - fixes #611 (#790) * Call gamma post process after `ui.render` #611 * Fixed "washed out" look. * Improve gamma pass and cache viewport size --- Minecraft.Client/Common/PostProcesser.h | 2 + .../Durango/Durango_Minecraft.cpp | 4 + Minecraft.Client/GameRenderer.cpp | 82 +++++++++++-------- Minecraft.Client/GameRenderer.h | 2 + Minecraft.Client/Orbis/Orbis_Minecraft.cpp | 4 + Minecraft.Client/PS3/PS3_Minecraft.cpp | 3 + Minecraft.Client/PSVita/PSVita_Minecraft.cpp | 4 + Minecraft.Client/Windows64/PostProcesser.cpp | 34 ++++---- .../Windows64/Windows64_Minecraft.cpp | 4 + 9 files changed, 90 insertions(+), 49 deletions(-) diff --git a/Minecraft.Client/Common/PostProcesser.h b/Minecraft.Client/Common/PostProcesser.h index ab7aedf6..35fa5080 100644 --- a/Minecraft.Client/Common/PostProcesser.h +++ b/Minecraft.Client/Common/PostProcesser.h @@ -45,6 +45,8 @@ private: bool m_wineMode = false; D3D11_VIEWPORT m_customViewport; bool m_useCustomViewport = false; + UINT m_gammaTexWidth = 0; + UINT m_gammaTexHeight = 0; struct GammaCBData { diff --git a/Minecraft.Client/Durango/Durango_Minecraft.cpp b/Minecraft.Client/Durango/Durango_Minecraft.cpp index a563c9f3..7fdab1be 100644 --- a/Minecraft.Client/Durango/Durango_Minecraft.cpp +++ b/Minecraft.Client/Durango/Durango_Minecraft.cpp @@ -27,6 +27,7 @@ #include "Leaderboards\DurangoLeaderboardManager.h" #include "..\..\Minecraft.Client\Tesselator.h" #include "..\..\Minecraft.Client\Options.h" +#include "..\GameRenderer.h" #include "Sentient\SentientManager.h" #include "..\..\Minecraft.World\IntCache.h" #include "..\Textures.h" @@ -832,6 +833,9 @@ void oldWinMainTick() #endif ui.tick(); ui.render(); + + pMinecraft->gameRenderer->ApplyGammaPostProcess(); + #if 0 app.HandleButtonPresses(); diff --git a/Minecraft.Client/GameRenderer.cpp b/Minecraft.Client/GameRenderer.cpp index 20a0f1e3..5790bea2 100644 --- a/Minecraft.Client/GameRenderer.cpp +++ b/Minecraft.Client/GameRenderer.cpp @@ -945,9 +945,9 @@ float GameRenderer::ComputeGammaFromSlider(float slider0to100) slider = min(slider, 100.0f); if (slider > 50.0f) - return 1.0f + (slider - 50.0f) / 50.0f * 3.0f; // 1.0 -> 4.0 + return 1.0f + (slider - 50.0f) / 50.0f * 0.5f; // 1.0 -> 1.5 else - return 1.0f - (50.0f - slider) / 50.0f * 0.85f; // 1.0 -> 0.15 + return 1.0f - (50.0f - slider) / 50.0f * 0.5f; // 1.0 -> 0.5 } void GameRenderer::CachePlayerGammas() @@ -1057,20 +1057,36 @@ void GameRenderer::ApplyGammaPostProcess() const D3D11_VIEWPORT vps[NUM_LIGHT_TEXTURES]; float gammas[NUM_LIGHT_TEXTURES]; const UINT n = BuildPlayerViewports(vps, gammas, NUM_LIGHT_TEXTURES); - if (n == 0) - return; - bool anyEffect = false; - for (UINT i = 0; i < n; ++i) + float gamma = 1.0f; + bool hasPlayers = n > 0; + + if (hasPlayers) { - if (gammas[i] < 0.99f || gammas[i] > 1.01f) + bool anyEffect = false; + for (UINT i = 0; i < n; ++i) { - anyEffect = true; - break; + if (gammas[i] < 0.99f || gammas[i] > 1.01f) + { + anyEffect = true; + break; + } } + if (!anyEffect) + return; } - if (!anyEffect) + else + { + const float slider = app.GetGameSettings(0, eGameSetting_Gamma); + gamma = ComputeGammaFromSlider(slider); + if (gamma < 0.99f || gamma > 1.01f) + { + PostProcesser::GetInstance().SetGamma(gamma); + PostProcesser::GetInstance().Apply(); + return; + } return; + } if (n == 1) { @@ -1175,35 +1191,33 @@ void GameRenderer::render(float a, bool bFirst) renderLevel(a, lastNsTime + 1000000000 / maxFps); } - lastNsTime = System::nanoTime(); + lastNsTime = System::nanoTime(); - if (!mc->options->hideGui || mc->screen != NULL) - { - mc->gui->render(a, mc->screen != NULL, xMouse, yMouse); + if (!mc->options->hideGui || mc->screen != NULL) + { + mc->gui->render(a, mc->screen != NULL, xMouse, yMouse); + } } - } - else - { - glViewport(0, 0, mc->width, mc->height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - setupGuiScreen(); + else + { + glViewport(0, 0, mc->width, mc->height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + setupGuiScreen(); - lastNsTime = System::nanoTime(); - } + lastNsTime = System::nanoTime(); + } - if (mc->screen != NULL) - { - glClear(GL_DEPTH_BUFFER_BIT); - mc->screen->render(xMouse, yMouse, a); - if (mc->screen != NULL && mc->screen->particles != NULL) mc->screen->particles->render(a); - } - - ApplyGammaPostProcess(); -} + if (mc->screen != NULL) + { + glClear(GL_DEPTH_BUFFER_BIT); + mc->screen->render(xMouse, yMouse, a); + if (mc->screen != NULL && mc->screen->particles != NULL) mc->screen->particles->render(a); + } + } void GameRenderer::renderLevel(float a) { diff --git a/Minecraft.Client/GameRenderer.h b/Minecraft.Client/GameRenderer.h index 21cf8acb..c379106e 100644 --- a/Minecraft.Client/GameRenderer.h +++ b/Minecraft.Client/GameRenderer.h @@ -81,7 +81,9 @@ private: float m_cachedGammaPerPlayer[NUM_LIGHT_TEXTURES]; static float ComputeGammaFromSlider(float slider0to100); void CachePlayerGammas(); +public: void ApplyGammaPostProcess() const; +private: bool ComputeViewportForPlayer(int j, D3D11_VIEWPORT& outViewport) const; uint32_t BuildPlayerViewports(D3D11_VIEWPORT* outViewports, float* outGammas, UINT maxCount) const; diff --git a/Minecraft.Client/Orbis/Orbis_Minecraft.cpp b/Minecraft.Client/Orbis/Orbis_Minecraft.cpp index 64616565..20b9dd03 100644 --- a/Minecraft.Client/Orbis/Orbis_Minecraft.cpp +++ b/Minecraft.Client/Orbis/Orbis_Minecraft.cpp @@ -32,6 +32,7 @@ //#include "NetworkManager.h" #include "..\..\Minecraft.Client\Tesselator.h" #include "..\..\Minecraft.Client\Options.h" +#include "..\GameRenderer.h" #include "Sentient\SentientManager.h" #include "..\..\Minecraft.World\IntCache.h" #include "..\Textures.h" @@ -1302,6 +1303,9 @@ int main(int argc, const char *argv[] ) #endif ui.tick(); ui.render(); + + pMinecraft->gameRenderer->ApplyGammaPostProcess(); + #if 0 app.HandleButtonPresses(); diff --git a/Minecraft.Client/PS3/PS3_Minecraft.cpp b/Minecraft.Client/PS3/PS3_Minecraft.cpp index 53b47d2d..82dd7c50 100644 --- a/Minecraft.Client/PS3/PS3_Minecraft.cpp +++ b/Minecraft.Client/PS3/PS3_Minecraft.cpp @@ -86,6 +86,7 @@ char secureFileId[CELL_SAVEDATA_SECUREFILEID_SIZE] = #include "..\..\Minecraft.Client\Tesselator.h" #include "..\Common\Console_Awards_enum.h" #include "..\..\Minecraft.Client\Options.h" +#include "..\GameRenderer.h" #include "Sentient\SentientManager.h" #include "..\..\Minecraft.World\IntCache.h" #include "..\Textures.h" @@ -1245,6 +1246,8 @@ int main() ui.tick(); ui.render(); + pMinecraft->gameRenderer->ApplyGammaPostProcess(); + // Present the frame. PIXBeginNamedEvent(0,"Frame present"); RenderManager.Present(); diff --git a/Minecraft.Client/PSVita/PSVita_Minecraft.cpp b/Minecraft.Client/PSVita/PSVita_Minecraft.cpp index a82adf00..7544c98d 100644 --- a/Minecraft.Client/PSVita/PSVita_Minecraft.cpp +++ b/Minecraft.Client/PSVita/PSVita_Minecraft.cpp @@ -46,6 +46,7 @@ #include "..\..\Minecraft.Client\Tesselator.h" #include "..\Common\Console_Awards_enum.h" #include "..\..\Minecraft.Client\Options.h" +#include "..\GameRenderer.h" #include "Sentient\SentientManager.h" #include "..\..\Minecraft.World\IntCache.h" #include "..\Textures.h" @@ -904,6 +905,9 @@ int main() #endif ui.tick(); ui.render(); + + pMinecraft->gameRenderer->ApplyGammaPostProcess(); + #if 0 app.HandleButtonPresses(); diff --git a/Minecraft.Client/Windows64/PostProcesser.cpp b/Minecraft.Client/Windows64/PostProcesser.cpp index 5abd83b4..4c55d3d9 100644 --- a/Minecraft.Client/Windows64/PostProcesser.cpp +++ b/Minecraft.Client/Windows64/PostProcesser.cpp @@ -28,7 +28,11 @@ const char* PostProcesser::g_gammaPSCode = "float4 main(float4 pos : SV_Position, float2 uv : TEXCOORD0) : SV_Target\n" "{\n" " float4 color = sceneTex.Sample(sceneSampler, uv);\n" - " color.rgb = pow(max(color.rgb, 0.0), 1.0 / gamma);\n" + "\n" + " color.rgb = max(color.rgb, 0.0);\n" + "\n" + " color.rgb = pow(color.rgb, 1.0 / gamma);\n" + "\n" " return color;\n" "}\n"; @@ -75,6 +79,9 @@ void PostProcesser::Init() pBackBuffer->GetDesc(&bbDesc); pBackBuffer->Release(); + m_gammaTexWidth = bbDesc.Width; + m_gammaTexHeight = bbDesc.Height; + DXGI_FORMAT texFormat = bbDesc.Format; if (m_wineMode) { @@ -219,7 +226,9 @@ void PostProcesser::Apply() const if (FAILED(hr)) return; - ctx->CopyResource(m_pGammaOffscreenTex, pBackBuffer); + D3D11_BOX srcBox = { 0, 0, 0, m_gammaTexWidth, m_gammaTexHeight, 1 }; + ctx->CopySubresourceRegion(m_pGammaOffscreenTex, 0, 0, 0, 0, pBackBuffer, 0, &srcBox); + pBackBuffer->Release(); D3D11_MAPPED_SUBRESOURCE mapped; const D3D11_MAP mapType = m_wineMode ? D3D11_MAP_WRITE_NO_OVERWRITE : D3D11_MAP_WRITE_DISCARD; @@ -236,16 +245,12 @@ void PostProcesser::Apply() const ctx->OMGetRenderTargets(1, &oldRTV, &oldDSV); UINT numViewports = 1; - D3D11_VIEWPORT oldViewport; + D3D11_VIEWPORT oldViewport = {}; ctx->RSGetViewports(&numViewports, &oldViewport); ID3D11RenderTargetView* bbRTV = g_pRenderTargetView; ctx->OMSetRenderTargets(1, &bbRTV, nullptr); - D3D11_TEXTURE2D_DESC bbDesc; - pBackBuffer->GetDesc(&bbDesc); - pBackBuffer->Release(); - D3D11_VIEWPORT vp; if (m_useCustomViewport) { @@ -253,8 +258,8 @@ void PostProcesser::Apply() const } else { - vp.Width = static_cast(bbDesc.Width); - vp.Height = static_cast(bbDesc.Height); + vp.Width = static_cast(m_gammaTexWidth); + vp.Height = static_cast(m_gammaTexHeight); vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; @@ -313,7 +318,8 @@ void PostProcesser::CopyBackbuffer() if (FAILED(hr)) return; - ctx->CopyResource(m_pGammaOffscreenTex, pBackBuffer); + D3D11_BOX srcBox = { 0, 0, 0, m_gammaTexWidth, m_gammaTexHeight, 1 }; + ctx->CopySubresourceRegion(m_pGammaOffscreenTex, 0, 0, 0, 0, pBackBuffer, 0, &srcBox); pBackBuffer->Release(); } @@ -342,7 +348,7 @@ void PostProcesser::ApplyFromCopied() const ctx->OMGetRenderTargets(1, &oldRTV, &oldDSV); UINT numViewports = 1; - D3D11_VIEWPORT oldViewport; + D3D11_VIEWPORT oldViewport = {}; ctx->RSGetViewports(&numViewports, &oldViewport); ID3D11RenderTargetView* bbRTV = g_pRenderTargetView; @@ -355,10 +361,8 @@ void PostProcesser::ApplyFromCopied() const } else { - D3D11_TEXTURE2D_DESC texDesc; - m_pGammaOffscreenTex->GetDesc(&texDesc); - vp.Width = static_cast(texDesc.Width); - vp.Height = static_cast(texDesc.Height); + vp.Width = static_cast(m_gammaTexWidth); + vp.Height = static_cast(m_gammaTexHeight); vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index dfb9b509..35afc694 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -44,6 +44,7 @@ #include "..\..\Minecraft.World\compression.h" #include "..\..\Minecraft.World\OldChunkStorage.h" #include "Common/PostProcesser.h" +#include "..\GameRenderer.h" #include "Network\WinsockNetLayer.h" #include "Windows64_Xuid.h" @@ -1517,6 +1518,9 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, #endif ui.tick(); ui.render(); + + pMinecraft->gameRenderer->ApplyGammaPostProcess(); + #if 0 app.HandleButtonPresses();