aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/GameRenderer.cpp
diff options
context:
space:
mode:
authorqwasdrizzel <145519042+qwasdrizzel@users.noreply.github.com>2026-03-05 17:17:45 -0600
committerGitHub <noreply@github.com>2026-03-05 17:17:45 -0600
commit0666959d312dc74903f55d1071488a90239330f1 (patch)
tree5c6886f7ec65a7828bc6e34a469514e418bcf78b /Minecraft.Client/GameRenderer.cpp
parent9370cbc7d878df1615d8ce76bc459e8b414d0f19 (diff)
parenteed770b121aa4ce38f002db042d0137c24c6d344 (diff)
Merge branch 'smartcmd:main' into main
Diffstat (limited to 'Minecraft.Client/GameRenderer.cpp')
-rw-r--r--Minecraft.Client/GameRenderer.cpp395
1 files changed, 262 insertions, 133 deletions
diff --git a/Minecraft.Client/GameRenderer.cpp b/Minecraft.Client/GameRenderer.cpp
index d3c5e8d3..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;
@@ -186,7 +187,7 @@ GameRenderer::~GameRenderer()
}
void GameRenderer::tick(bool first) // 4J - add bFirst
-{
+{
tickFov();
tickLightTexture(); // 4J - change brought forward from 1.8.2
fogBrO = fogBr;
@@ -308,11 +309,9 @@ void GameRenderer::pick(float a)
vector<shared_ptr<Entity> > *objects = mc->level->getEntities(mc->cameraTargetPlayer, mc->cameraTargetPlayer->bb->expand(b->x * (range), b->y * (range), b->z * (range))->grow(overlap, overlap, overlap));
double nearest = dist;
- AUTO_VAR(itEnd, objects->end());
- for (AUTO_VAR(it, objects->begin()); it != itEnd; it++)
- {
- shared_ptr<Entity> e = *it; //objects->at(i);
- if (!e->isPickable()) continue;
+ for (auto& e : *objects )
+ {
+ if ( e == nullptr || !e->isPickable() ) continue;
float rr = e->getPickRadius();
AABB *bb = e->bb->grow(rr, rr, rr);
@@ -325,7 +324,7 @@ void GameRenderer::pick(float a)
nearest = 0;
}
}
- else if (p != NULL)
+ else if (p != nullptr)
{
double dd = from->distanceTo(p->pos);
if (e == mc->cameraTargetPlayer->riding != NULL)
@@ -335,7 +334,7 @@ void GameRenderer::pick(float a)
hovered = e;
}
}
- else
+ else
{
hovered = e;
nearest = dd;
@@ -595,7 +594,7 @@ void GameRenderer::unZoomRegion()
void GameRenderer::getFovAndAspect(float& fov, float& aspect, float a, bool applyEffects)
{
// 4J - split out aspect ratio and fov here so we can adjust for viewports - we might need to revisit these as
- // they are maybe be too generous for performance.
+ // they are maybe be too generous for performance.
aspect = mc->width / (float) mc->height;
fov = getFov(a, applyEffects);
@@ -735,14 +734,14 @@ void GameRenderer::renderItemInHand(float a, int eye)
bool bNoLegAnim =(localplayer->getAnimOverrideBitmask()&( (1<<HumanoidModel::eAnim_NoLegAnim) | (1<<HumanoidModel::eAnim_NoBobbing) ))!=0;
if(app.GetGameSettings(localplayer->GetXboxPad(),eGameSetting_ViewBob) && !localplayer->abilities.flying && !bNoLegAnim) bobView(a);
- // 4J: Skip hand rendering if render hand is off
+ // 4J: Skip hand rendering if render hand is off
if (renderHand)
{
// 4J-PB - changing this to be per player
//if (!mc->options->thirdPersonView && !mc->cameraTargetPlayer->isSleeping())
if (!localplayer->ThirdPersonView() && !mc->cameraTargetPlayer->isSleeping())
{
- if (!mc->options->hideGui && !mc->gameMode->isCutScene())
+ if (!mc->options->hideGui && !mc->gameMode->isCutScene())
{
turnOnLightLayer(a);
PIXBeginNamedEvent(0,"Item in hand render");
@@ -770,7 +769,7 @@ void GameRenderer::renderItemInHand(float a, int eye)
// 4J - change brought forward from 1.8.2
void GameRenderer::turnOffLightLayer(double alpha)
{ // 4J - TODO
-#if 0
+#if 0
if (SharedConstants::TEXTURE_LIGHTING)
{
glClientActiveTexture(GL_TEXTURE1);
@@ -834,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];
- }
-
- 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);
-
- _r = _r * 0.96f + 0.03f;
- _g = _g * 0.96f + 0.03f;
- _b = _b * 0.96f + 0.03f;
-
- 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;
- }
-
- 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))
- {
- 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) _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);
+ CachePlayerGammas();
+
+ 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);
#if ( defined _DURANGO || defined _WIN64 || __PSVITA__ )
- lightPixels[j][i] = alpha << 24 | b << 16 | g << 8 | r;
+ 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;
+ lightPixels[j][i] = alpha << 24 | r << 16 | g << 8 | b;
#else
- lightPixels[j][i] = r << 24 | g << 16 | b << 8 | alpha;
+ lightPixels[j][i] = r << 24 | g << 16 | b << 8 | alpha;
#endif
- }
+ }
- mc->textures->replaceTextureDirect( lightPixels[j], 16, 16, getLightTexture(j,level) );
- // lightTexture->upload(); // 4J: not relevant
+ mc->textures->replaceTextureDirect(lightPixels[j], 16, 16, getLightTexture(j, level));
+ }
+}
- //_updateLightTexture = false;
- }
+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
+}
+
+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);
+ }
+}
+
+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 (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;
+ }
+}
+
+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;
+}
+
+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)
@@ -1041,6 +1169,7 @@ void GameRenderer::render(float a, bool bFirst)
lastNsTime = System::nanoTime();
+ ApplyGammaPostProcess();
if (!mc->options->hideGui || mc->screen != NULL)
{
@@ -1111,7 +1240,7 @@ int GameRenderer::runUpdate(LPVOID lpParam)
Vec3::CreateNewThreadStorage();
AABB::CreateNewThreadStorage();
IntCache::CreateNewThreadStorage();
- Tesselator::CreateNewThreadStorage(1024*1024);
+ Tesselator::CreateNewThreadStorage(1024*1024);
Compression::UseDefaultThreadStorage();
RenderManager.InitialiseContext();
#ifdef _LARGE_WORLDS
@@ -1185,7 +1314,7 @@ int GameRenderer::runUpdate(LPVOID lpParam)
AABB::resetPool();
Vec3::resetPool();
- IntCache::Reset();
+ IntCache::Reset();
m_updateEvents->Set(eUpdateEventIsFinished);
}
@@ -1217,7 +1346,7 @@ void GameRenderer::DisableUpdateThread()
if( !updateRunning) return;
app.DebugPrintf("------------------DisableUpdateThread--------------------\n");
updateRunning = false;
- m_updateEvents->Clear(eUpdateCanRun);
+ m_updateEvents->Clear(eUpdateCanRun);
m_updateEvents->WaitForSingle(eUpdateEventIsFinished,INFINITE);
#endif
}
@@ -1588,7 +1717,7 @@ void GameRenderer::renderSnowAndRain(float a)
turnOnLightLayer(a);
- if (rainXa == NULL)
+ if (rainXa == NULL)
{
rainXa = new float[32 * 32];
rainZa = new float[32 * 32];
@@ -1709,9 +1838,9 @@ void GameRenderer::renderSnowAndRain(float a)
float Alpha = ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel;
int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
t->tileRainQuad(x - xa + 0.5, yy0, z - za + 0.5, 0 * s, yy0 * s / 4.0f + ra * s,
- x + xa + 0.5, yy0, z + za + 0.5, 1 * s, yy0 * s / 4.0f + ra * s,
- x + xa + 0.5, yy1, z + za + 0.5, 1 * s, yy1 * s / 4.0f + ra * s,
- x - xa + 0.5, yy1, z - za + 0.5, 0 * s, yy1 * s / 4.0f + ra * s,
+ x + xa + 0.5, yy0, z + za + 0.5, 1 * s, yy0 * s / 4.0f + ra * s,
+ x + xa + 0.5, yy1, z + za + 0.5, 1 * s, yy1 * s / 4.0f + ra * s,
+ x - xa + 0.5, yy1, z - za + 0.5, 0 * s, yy1 * s / 4.0f + ra * s,
br, br, br, Alpha, br, br, br, 0, tex2);
#else
t->tex2(level->getLightColor(x, yl, z, 0));
@@ -1747,9 +1876,9 @@ void GameRenderer::renderSnowAndRain(float a)
float Alpha = ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel;
int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
t->tileRainQuad(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo, yy0 * s / 4.0f + ra * s + vo,
- x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo, yy0 * s / 4.0f + ra * s + vo,
- x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo, yy1 * s / 4.0f + ra * s + vo,
- x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo, yy1 * s / 4.0f + ra * s + vo,
+ x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo, yy0 * s / 4.0f + ra * s + vo,
+ x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo, yy1 * s / 4.0f + ra * s + vo,
+ x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo, yy1 * s / 4.0f + ra * s + vo,
br, br, br, Alpha, br, br, br, Alpha, tex2);
#else
t->tex2((level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4);