diff options
| author | ModMaker101 <119018978+ModMaker101@users.noreply.github.com> | 2026-03-05 14:41:17 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-06 02:41:17 +0700 |
| commit | cbcf3de358f97ae1f687f3ffa47fcdb910e39bcb (patch) | |
| tree | 35e2e226b669496319c978d026045b0ebe91ef89 /Minecraft.Client/GameRenderer.cpp | |
| parent | 55231bb8d3e1a4e2752ac3d444c4287eb0ca4e8b (diff) | |
Fix gamma slider via pixel shader #178 (#481)
* Fix gamma slider via pixel shader #178
* LCE-like gamma using postprocess shader
Diffstat (limited to 'Minecraft.Client/GameRenderer.cpp')
| -rw-r--r-- | Minecraft.Client/GameRenderer.cpp | 349 |
1 files changed, 240 insertions, 109 deletions
diff --git a/Minecraft.Client/GameRenderer.cpp b/Minecraft.Client/GameRenderer.cpp index 5a936c82..390f114d 100644 --- a/Minecraft.Client/GameRenderer.cpp +++ b/Minecraft.Client/GameRenderer.cpp @@ -51,6 +51,7 @@ #include "TexturePackRepository.h" #include "TexturePack.h" #include "TextureAtlas.h" +#include "Common/PostProcesser.h" bool GameRenderer::anaglyph3d = false; int GameRenderer::anaglyphPass = 0; @@ -832,124 +833,253 @@ void GameRenderer::tickLightTexture() void GameRenderer::updateLightTexture(float a) { - // 4J-JEV: Now doing light textures on PER PLAYER basis. - // 4J - we *had* added separate light textures for all dimensions, and this loop to update them all here - for(int j = 0; j < XUSER_MAX_COUNT; j++ ) - { - // Loop over all the players - shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[j]; - if (player == NULL) continue; - - Level *level = player->level; // 4J - was mc->level when it was just to update the one light texture - - float skyDarken1 = level->getSkyDarken((float) 1); - for (int i = 0; i < 256; i++) - { - float darken = skyDarken1 * 0.95f + 0.05f; - float sky = level->dimension->brightnessRamp[i / 16] * darken; - float block = level->dimension->brightnessRamp[i % 16] * (blr * 0.1f + 1.5f); - - if (level->skyFlashTime > 0) - { - sky = level->dimension->brightnessRamp[i / 16]; - } + CachePlayerGammas(); - float rs = sky * (skyDarken1 * 0.65f + 0.35f); - float gs = sky * (skyDarken1 * 0.65f + 0.35f); - float bs = sky; - - float rb = block; - float gb = block * ((block * 0.6f + 0.4f) * 0.6f + 0.4f); - float bb = block * ((block * block) * 0.6f + 0.4f); - - float _r = (rs + rb); - float _g = (gs + gb); - float _b = (bs + bb); + for (int j = 0; j < XUSER_MAX_COUNT; j++) + { + shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[j]; + if (player == nullptr) + continue; + + Level *level = player->level; + + const float skyDarken1 = level->getSkyDarken(1.0f); + for (int i = 0; i < 256; i++) + { + const float darken = skyDarken1 * 0.95f + 0.05f; + float sky = level->dimension->brightnessRamp[i / 16] * darken; + const float block = level->dimension->brightnessRamp[i % 16] * (blr * 0.1f + 1.5f); + + if (level->skyFlashTime < 0) + { + sky = level->dimension->brightnessRamp[i / 16]; + } + + const float rs = sky * (skyDarken1 * 0.65f + 0.35f); + const float gs = sky * (skyDarken1 * 0.65f + 0.35f); + const float bs = sky; + + const float rb = block; + const float gb = block * ((block * 0.6f + 0.4f) * 0.6f + 0.4f); + const float bb = block * ((block * block) * 0.6f + 0.4f); + + float _r = (rs + rb); + float _g = (gs + gb); + float _b = (bs + bb); + + _r = _r * 0.96f + 0.03f; + _g = _g * 0.96f + 0.03f; + _b = _b * 0.96f + 0.03f; + + if (darkenWorldAmount > 0) + { + const float amount = darkenWorldAmountO + (darkenWorldAmount - darkenWorldAmountO) * a; + _r = _r * (1.0f - amount) + (_r * 0.7f) * amount; + _g = _g * (1.0f - amount) + (_g * 0.6f) * amount; + _b = _b * (1.0f - amount) + (_b * 0.6f) * amount; + } + + if (level->dimension->id == 1) + { + _r = (0.22f + rb * 0.75f); + _g = (0.28f + gb * 0.75f); + _b = (0.25f + bb * 0.75f); + } + + if (player->hasEffect(MobEffect::nightVision)) + { + const float scale = getNightVisionScale(player, a); + float dist = 1.0f / _r; + if (dist > (1.0f / _g)) + dist = (1.0f / _g); + if (dist > (1.0f / _b)) + dist = (1.0f / _b); + _r = _r * (1.0f - scale) + (_r * dist) * scale; + _g = _g * (1.0f - scale) + (_g * dist) * scale; + _b = _b * (1.0f - scale) + (_b * dist) * scale; + } + + if (_r > 1.0f) + _r = 1.0f; + if (_r < 0.0f) + _r = 0.0f; + if (_g > 1.0f) + _g = 1.0f; + if (_g < 0.0f) + _g = 0.0f; + if (_b > 1.0f) + _b = 1.0f; + if (_b < 0.0f) + _b = 0.0f; + + constexpr int alpha = 255; + const int r = static_cast<int>(_r * 255); + const int g = static_cast<int>(_g * 255); + const int b = static_cast<int>(_b * 255); - _r = _r * 0.96f + 0.03f; - _g = _g * 0.96f + 0.03f; - _b = _b * 0.96f + 0.03f; +#if ( defined _DURANGO || defined _WIN64 || __PSVITA__ ) + lightPixels[j][i] = alpha << 24 | b << 16 | g << 8 | r; +#elif ( defined _XBOX || defined __ORBIS__ ) + lightPixels[j][i] = alpha << 24 | r << 16 | g << 8 | b; +#else + lightPixels[j][i] = r << 24 | g << 16 | b << 8 | alpha; +#endif + } - if (darkenWorldAmount > 0) - { - float amount = darkenWorldAmountO + (darkenWorldAmount - darkenWorldAmountO) * a; - _r = _r * (1.0f - amount) + (_r * .7f) * amount; - _g = _g * (1.0f - amount) + (_g * .6f) * amount; - _b = _b * (1.0f - amount) + (_b * .6f) * amount; - } + mc->textures->replaceTextureDirect(lightPixels[j], 16, 16, getLightTexture(j, level)); + } +} - if (level->dimension->id == 1) - { - _r = (0.22f + rb * 0.75f); - _g = (0.28f + gb * 0.75f); - _b = (0.25f + bb * 0.75f); - } +float GameRenderer::ComputeGammaFromSlider(float slider0to100) +{ + float slider = slider0to100; + slider = max(slider, 0.0f); + slider = min(slider, 100.0f); + + if (slider > 50.0f) + return 1.0f + (slider - 50.0f) / 50.0f * 3.0f; // 1.0 -> 4.0 + else + return 1.0f - (50.0f - slider) / 50.0f * 0.85f; // 1.0 -> 0.15 +} - if (player->hasEffect(MobEffect::nightVision)) - { - float scale = getNightVisionScale(player, a); - { - float dist = 1.0f / _r; - if (dist > (1.0f / _g)) - { - dist = (1.0f / _g); - } - if (dist > (1.0f / _b)) - { - dist = (1.0f / _b); - } - _r = _r * (1.0f - scale) + (_r * dist) * scale; - _g = _g * (1.0f - scale) + (_g * dist) * scale; - _b = _b * (1.0f - scale) + (_b * dist) * scale; - } - } +void GameRenderer::CachePlayerGammas() +{ + for (int j = 0; j < XUSER_MAX_COUNT && j < NUM_LIGHT_TEXTURES; ++j) + { + std::shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[j]; + if (!player) + { + m_cachedGammaPerPlayer[j] = 1.0f; + continue; + } + + const float slider = app.GetGameSettings(j, eGameSetting_Gamma); // 0..100 + m_cachedGammaPerPlayer[j] = ComputeGammaFromSlider(slider); + } +} - if (_r > 1) _r = 1; - if (_g > 1) _g = 1; - if (_b > 1) _b = 1; - - float brightness = mc->options->gamma; - - float ir = 1 - _r; - float ig = 1 - _g; - float ib = 1 - _b; - ir = 1 - (ir * ir * ir * ir); - ig = 1 - (ig * ig * ig * ig); - ib = 1 - (ib * ib * ib * ib); - _r = _r * (1 - brightness) + ir * brightness; - _g = _g * (1 - brightness) + ig * brightness; - _b = _b * (1 - brightness) + ib * brightness; - - _r = _r * 0.96f + 0.03f; - _g = _g * 0.96f + 0.03f; - _b = _b * 0.96f + 0.03f; - - if (_r > 1) _r = 1; - if (_g > 1) _g = 1; - if (_b > 1) _b = 1; - if (_r < 0) _r = 0; - if (_g < 0) _g = 0; - if (_b < 0) _b = 0; - - int alpha = 255; - int r = (int) (_r * 255); - int g = (int) (_g * 255); - int b = (int) (_b * 255); +bool GameRenderer::ComputeViewportForPlayer(int j, D3D11_VIEWPORT &outViewport) const +{ + int active = 0; + int indexMap[NUM_LIGHT_TEXTURES] = {-1, -1, -1, -1}; + for (int i = 0; i < XUSER_MAX_COUNT && i < NUM_LIGHT_TEXTURES; ++i) + { + if (Minecraft::GetInstance()->localplayers[i]) + indexMap[active++] = i; + } -#if ( defined _DURANGO || defined _WIN64 || __PSVITA__ ) - lightPixels[j][i] = alpha << 24 | b << 16 | g << 8 | r; -#elif ( defined _XBOX || defined __ORBIS__ ) - lightPixels[j][i] = alpha << 24 | r << 16 | g << 8 | b; -#else - lightPixels[j][i] = r << 24 | g << 16 | b << 8 | alpha; -#endif - } + if (active <= 1) + { + outViewport.TopLeftX = 0.0f; + outViewport.TopLeftY = 0.0f; + outViewport.Width = static_cast<FLOAT>(mc->width); + outViewport.Height = static_cast<FLOAT>(mc->height); + outViewport.MinDepth = 0.0f; + outViewport.MaxDepth = 1.0f; + return true; + } + + int k = -1; + for (int ord = 0; ord < active; ++ord) + if (indexMap[ord] == j) + { + k = ord; + break; + } + if (k < 0) + return false; + + const float width = static_cast<float>(mc->width); + const float height = static_cast<float>(mc->height); + + if (active == 2) + { + const float halfH = height * 0.5f; + outViewport.TopLeftX = 0.0f; + outViewport.Width = width; + outViewport.MinDepth = 0.0f; + outViewport.MaxDepth = 1.0f; + if (k == 0) + { + outViewport.TopLeftY = 0.0f; + outViewport.Height = halfH; + } + else + { + outViewport.TopLeftY = halfH; + outViewport.Height = halfH; + } + return true; + } + else + { + const float halfW = width * 0.5f; + const float halfH = height * 0.5f; + const int row = (k >= 2) ? 1 : 0; + const int col = (k % 2); + outViewport.TopLeftX = col ? halfW : 0.0f; + outViewport.TopLeftY = row ? halfH : 0.0f; + outViewport.Width = halfW; + outViewport.Height = halfH; + outViewport.MinDepth = 0.0f; + outViewport.MaxDepth = 1.0f; + return true; + } +} - mc->textures->replaceTextureDirect( lightPixels[j], 16, 16, getLightTexture(j,level) ); - // lightTexture->upload(); // 4J: not relevant +uint32_t GameRenderer::BuildPlayerViewports(D3D11_VIEWPORT *outViewports, float *outGammas, UINT maxCount) const +{ + UINT count = 0; + for (int j = 0; j < XUSER_MAX_COUNT && j < NUM_LIGHT_TEXTURES && count < maxCount; ++j) + { + if (!Minecraft::GetInstance()->localplayers[j]) + continue; + D3D11_VIEWPORT vp; + if (!ComputeViewportForPlayer(j, vp)) + continue; + outViewports[count] = vp; + outGammas[count] = m_cachedGammaPerPlayer[j]; + ++count; + } + return count; +} - //_updateLightTexture = false; - } +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) + { + if (gammas[i] < 0.99f || gammas[i] > 1.01f) + { + anyEffect = true; + break; + } + } + if (!anyEffect) + return; + + if (n == 1) + { + PostProcesser::GetInstance().SetGamma(gammas[0]); + PostProcesser::GetInstance().Apply(); + } + else + { + PostProcesser::GetInstance().CopyBackbuffer(); + for (UINT i = 0; i < n; ++i) + { + PostProcesser::GetInstance().SetGamma(gammas[i]); + PostProcesser::GetInstance().SetViewport(vps[i]); + PostProcesser::GetInstance().ApplyFromCopied(); + } + PostProcesser::GetInstance().ResetViewport(); + } } float GameRenderer::getNightVisionScale(shared_ptr<Player> player, float a) @@ -1039,6 +1169,7 @@ void GameRenderer::render(float a, bool bFirst) lastNsTime = System::nanoTime(); + ApplyGammaPostProcess(); if (!mc->options->hideGui || mc->screen != NULL) { |
