Add dynamic lighting with Fast/Fancy quality toggle

This commit is contained in:
MCbabel 2026-03-18 04:12:02 +01:00
parent a94ee1ca22
commit 582369d54f
16 changed files with 245 additions and 4 deletions

View file

@ -105,6 +105,9 @@ enum EGameHostOptionWorldSize
#define GAMESETTING_PS3EULAREAD 0x00010000
#define GAMESETTING_PSVITANETWORKMODEADHOC 0x00020000
// Dynamic Lighting (bits 24-25)
#define GAMESETTING_DYNAMICLIGHTING 0x01000000
#define GAMESETTING_DYNLIGHTMODE 0x02000000
// defines for languages

View file

@ -178,7 +178,9 @@ enum eGameSetting
// PSVita
eGameSetting_PSVita_NetworkModeAdhoc,
// Dynamic Lighting
eGameSetting_DynamicLighting,
eGameSetting_DynLightMode,
};

View file

@ -900,6 +900,10 @@ int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,con
// TU 7
SetGameSettings(iPad,eGameSetting_CustomSkinAnim,1);
// Dynamic Lighting
SetGameSettings(iPad,eGameSetting_DynamicLighting,1);
SetGameSettings(iPad,eGameSetting_DynLightMode,1); // 0=Fast, 1=Fancy
// TU 9
SetGameSettings(iPad,eGameSetting_DeathMessages,1);
SetGameSettings(iPad,eGameSetting_UISize,1);
@ -2328,6 +2332,17 @@ void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucV
}
break;
case eGameSetting_DynamicLighting:
if(ucVal) GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_DYNAMICLIGHTING;
else GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_DYNAMICLIGHTING;
GameSettingsA[iPad]->bSettingsChanged = true;
break;
case eGameSetting_DynLightMode:
if(ucVal) GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_DYNLIGHTMODE;
else GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_DYNLIGHTMODE;
GameSettingsA[iPad]->bSettingsChanged = true;
break;
}
}
@ -2463,6 +2478,11 @@ unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal)
case eGameSetting_PSVita_NetworkModeAdhoc:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)>>17;
case eGameSetting_DynamicLighting:
return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_DYNAMICLIGHTING) ? 1 : 0;
case eGameSetting_DynLightMode:
return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_DYNLIGHTMODE) ? 1 : 0;
}
return 0;
}

View file

@ -2,6 +2,7 @@
#include "UI.h"
#include "UIScene_SettingsGraphicsMenu.h"
#include "..\..\Minecraft.h"
#include "..\..\MultiPlayerLevel.h"
#include "..\..\Options.h"
#include "..\..\GameRenderer.h"
@ -63,7 +64,9 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD
m_checkboxBedrockFog.init(app.GetString(IDS_CHECKBOX_RENDER_BEDROCKFOG),eControl_BedrockFog,(app.GetGameSettings(m_iPad,eGameSetting_BedrockFog)!=0));
m_checkboxCustomSkinAnim.init(app.GetString(IDS_CHECKBOX_CUSTOM_SKIN_ANIM),eControl_CustomSkinAnim,(app.GetGameSettings(m_iPad,eGameSetting_CustomSkinAnim)!=0));
m_checkboxDynLight.init(L"Dynamic Lighting", eControl_DynamicLighting,
(app.GetGameSettings(m_iPad, eGameSetting_DynamicLighting) != 0));
WCHAR TempString[256];
swprintf(TempString, 256, L"Render Distance: %d",app.GetGameSettings(m_iPad,eGameSetting_RenderDistance));
@ -80,6 +83,12 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD
swprintf( TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_INTERFACEOPACITY ),app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity));
m_sliderInterfaceOpacity.init(TempString,eControl_InterfaceOpacity,0,100,app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity));
{
int dynMode = app.GetGameSettings(m_iPad, eGameSetting_DynLightMode);
m_sliderDynLightMode.init(dynMode ? L"Dynamic Light Mode: Fancy" : L"Dynamic Light Mode: Fast",
eControl_DynLightMode, 0, 1, dynMode);
}
doHorizontalResizeCheck();
const bool bInGame=(Minecraft::GetInstance()->level!=nullptr);
@ -166,6 +175,17 @@ void UIScene_SettingsGraphicsMenu::handleInput(int iPad, int key, bool repeat, b
app.SetGameSettings(m_iPad,eGameSetting_BedrockFog,m_checkboxBedrockFog.IsChecked()?1:0);
app.SetGameSettings(m_iPad,eGameSetting_CustomSkinAnim,m_checkboxCustomSkinAnim.IsChecked()?1:0);
{
bool dynEnabled = m_checkboxDynLight.IsChecked();
app.SetGameSettings(m_iPad, eGameSetting_DynamicLighting, dynEnabled ? 1 : 0);
Minecraft *mc = Minecraft::GetInstance();
if (mc && mc->level)
{
mc->level->m_dynLightsEnabled = dynEnabled;
mc->level->m_dynLightFancy = (app.GetGameSettings(m_iPad, eGameSetting_DynLightMode) != 0);
}
}
navigateBack();
handled = true;
}
@ -236,5 +256,17 @@ void UIScene_SettingsGraphicsMenu::handleSliderMove(F64 sliderId, F64 currentVal
m_sliderInterfaceOpacity.setLabel(TempString);
break;
case eControl_DynLightMode:
{
m_sliderDynLightMode.handleSliderMove(value);
bool fancy = (value != 0);
m_sliderDynLightMode.setLabel(fancy ? L"Dynamic Light Mode: Fancy" : L"Dynamic Light Mode: Fast");
app.SetGameSettings(m_iPad, eGameSetting_DynLightMode, fancy ? 1 : 0);
Minecraft *mc = Minecraft::GetInstance();
if (mc && mc->level)
mc->level->m_dynLightFancy = fancy;
}
break;
}
}

View file

@ -15,11 +15,15 @@ private:
eControl_RenderDistance,
eControl_Gamma,
eControl_FOV,
eControl_InterfaceOpacity
eControl_InterfaceOpacity,
eControl_DynamicLighting,
eControl_DynLightMode
};
UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim; // Checkboxes
UIControl_CheckBox m_checkboxDynLight;
UIControl_Slider m_sliderRenderDistance, m_sliderGamma, m_sliderFOV, m_sliderInterfaceOpacity; // Sliders
UIControl_Slider m_sliderDynLightMode;
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
UI_MAP_ELEMENT( m_checkboxClouds, "Clouds")
UI_MAP_ELEMENT( m_checkboxBedrockFog, "BedrockFog")
@ -28,6 +32,8 @@ private:
UI_MAP_ELEMENT( m_sliderGamma, "Gamma")
UI_MAP_ELEMENT(m_sliderFOV, "FOV")
UI_MAP_ELEMENT( m_sliderInterfaceOpacity, "InterfaceOpacity")
UI_MAP_ELEMENT( m_checkboxDynLight, "DynamicLighting")
UI_MAP_ELEMENT( m_sliderDynLightMode, "DynLightMode")
UI_END_MAP_ELEMENTS_AND_NAMES()
bool m_bNotInGame;

View file

@ -2323,7 +2323,16 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
// soundEngine.playMusicTick();
if (!pause && level != nullptr) gameMode->tick();
if (!pause && level != nullptr)
{
gameMode->tick();
if (player != nullptr)
{
level->m_dynLightsEnabled = (app.GetGameSettings(0, eGameSetting_DynamicLighting) != 0);
level->m_dynLightFancy = (app.GetGameSettings(0, eGameSetting_DynLightMode) != 0);
level->updateDynamicLights();
}
}
MemSect(31);
glBindTexture(GL_TEXTURE_2D, textures->loadTexture(TN_TERRAIN)); //L"/terrain.png"));
MemSect(0);

View file

@ -503,6 +503,18 @@ void Item::staticInit()
Stats::buildItemStats();
}
int Item::getItemLightLevel(shared_ptr<ItemInstance> item)
{
if (!item || item->id == 0) return 0;
if (item->id < 256 && Tile::lightEmission[item->id] > 0)
return Tile::lightEmission[item->id];
if (item->id == bucket_lava_Id) return 15;
return 0;
}
_Tier::Tier(int level, int uses, float speed, float damage, int enchantmentValue) :
level( level ),

View file

@ -35,6 +35,7 @@ public:
static void staticCtor();
static void staticInit();
static int getItemLightLevel(shared_ptr<ItemInstance> item);
// 4J-PB - added for new crafting menu
enum

View file

@ -27,6 +27,8 @@
#include "ThreadName.h"
#include "WeighedRandom.h"
#include "net.minecraft.world.item.h"
#include "net.minecraft.world.entity.item.h"
#include "ConsoleSaveFile.h"
#include <xuiapp.h>
#include "..\Minecraft.Client\Minecraft.h"
@ -595,6 +597,10 @@ void Level::_init()
m_bDisableAddNewTileEntities = false;
m_iHighestY=-1000;
m_unsavedChunkCount = 0;
m_dynLightsEnabled = true;
m_dynLightsReady = false;
m_dynLightFancy = true;
InitializeCriticalSection(&m_dynLightCS);
}
// 4J - brought forward from 1.8.2
@ -1458,6 +1464,8 @@ int Level::getLightColor(int x, int y, int z, int emitt, int tileId/*=-1*/)
{
int s = getBrightnessPropagate(LightLayer::Sky, x, y, z, tileId);
int b = getBrightnessPropagate(LightLayer::Block, x, y, z, tileId);
int dyn = getDynamicLight(x, y, z);
if (dyn > b) b = dyn;
if (b < emitt) b = emitt;
return s << 20 | b << 4;
}
@ -3128,6 +3136,137 @@ void Level::tick()
PIXEndNamedEvent();
}
static int getEntityLightLevel(shared_ptr<Entity> e)
{
if (!e || e->removed) return 0;
eINSTANCEOF type = e->GetType();
if (type & eTYPE_PLAYER)
return Item::getItemLightLevel(((Player *)e.get())->getCarriedItem());
if (type == eTYPE_ITEMENTITY)
return Item::getItemLightLevel(((ItemEntity *)e.get())->getItem());
if (type == eTYPE_BLAZE) return 7;
if ((type & eTYPE_MOB) || type == eTYPE_ARROW)
if (e->isOnFire()) return 15;
return 0;
}
int Level::getDynamicLight(int x, int y, int z)
{
if (!m_dynLightsReady) return 0;
if (y >= 0 && y < maxBuildHeight)
{
int t = getTile(x, y, z);
if (t > 0 && Tile::lightBlock[t] >= 15) return 0;
}
int best = 0;
EnterCriticalSection(&m_dynLightCS);
for (size_t i = 0; i < m_dynLightSources.size(); i++)
{
DynLightSource &src = m_dynLightSources[i];
float dx = (float)x - src.x, dy = (float)y - src.y, dz = (float)z - src.z;
int dist;
if (m_dynLightFancy)
dist = (int)(sqrtf(dx * dx + dy * dy + dz * dz) + 0.5f);
else
dist = (int)(fabsf(dx) + fabsf(dy) + fabsf(dz));
int val = src.level - dist;
if (val > best) best = val;
}
LeaveCriticalSection(&m_dynLightCS);
return best;
}
void Level::updateDynamicLights()
{
if (players.empty() || !chunkSource) return;
if (!m_dynLightsEnabled)
{
if (m_dynLightsReady)
{
EnterCriticalSection(&m_dynLightCS);
m_dynLightSources.clear();
LeaveCriticalSection(&m_dynLightCS);
for (size_t i = 0; i < m_prevDynLightAreas.size(); i++)
{
DynLightPrev &prev = m_prevDynLightAreas[i];
setTilesDirty(prev.x - prev.radius, prev.y - prev.radius, prev.z - prev.radius,
prev.x + prev.radius, prev.y + prev.radius, prev.z + prev.radius);
}
m_prevDynLightAreas.clear();
m_dynLightsReady = false;
}
return;
}
m_dynLightsReady = true;
for (size_t i = 0; i < m_prevDynLightAreas.size(); i++)
{
DynLightPrev &prev = m_prevDynLightAreas[i];
setTilesDirty(prev.x - prev.radius, prev.y - prev.radius, prev.z - prev.radius,
prev.x + prev.radius, prev.y + prev.radius, prev.z + prev.radius);
}
m_prevDynLightAreas.clear();
vector<DynLightSource> newSources;
int maxRadius = m_dynLightFancy ? 10 : 6;
for (size_t i = 0; i < players.size(); i++)
{
if (!players[i]) continue;
int ll = getEntityLightLevel(players[i]);
if (ll <= 0) continue;
if (ll > MAX_BRIGHTNESS) ll = MAX_BRIGHTNESS;
newSources.push_back({(float)players[i]->x, (float)players[i]->y, (float)players[i]->z, ll});
}
if (m_dynLightFancy && TryEnterCriticalSection(&m_entitiesCS))
{
for (size_t i = 0; i < entities.size(); i++)
{
shared_ptr<Entity> e = entities[i];
if (!e || e->removed) continue;
int ll = 0;
eINSTANCEOF type = e->GetType();
if (type == eTYPE_ITEMENTITY)
ll = Item::getItemLightLevel(((ItemEntity *)e.get())->getItem());
else if (type == eTYPE_BLAZE)
ll = 7;
else if ((type & eTYPE_MOB) || type == eTYPE_ARROW)
if (e->isOnFire()) ll = 15;
if (ll <= 0) continue;
if (ll > MAX_BRIGHTNESS) ll = MAX_BRIGHTNESS;
newSources.push_back({(float)e->x, (float)e->y, (float)e->z, ll});
}
LeaveCriticalSection(&m_entitiesCS);
}
EnterCriticalSection(&m_dynLightCS);
m_dynLightSources.swap(newSources);
LeaveCriticalSection(&m_dynLightCS);
for (size_t i = 0; i < m_dynLightSources.size(); i++)
{
DynLightSource &src = m_dynLightSources[i];
int r = min(src.level, maxRadius);
int sx = Mth::floor(src.x), sy = Mth::floor(src.y), sz = Mth::floor(src.z);
setTilesDirty(sx - r, sy - r, sz - r, sx + r, sy + r, sz + r);
m_prevDynLightAreas.push_back({sx, sy, sz, r});
}
}
void Level::prepareWeather()
{
if (levelData->isRaining())

View file

@ -161,6 +161,19 @@ public:
shared_ptr<Villages> villages;
VillageSiege *villageSiege;
// Dynamic lighting
bool m_dynLightsEnabled;
bool m_dynLightsReady;
bool m_dynLightFancy;
struct DynLightSource { float x, y, z; int level; };
vector<DynLightSource> m_dynLightSources;
struct DynLightPrev { int x, y, z, radius; };
vector<DynLightPrev> m_prevDynLightAreas;
CRITICAL_SECTION m_dynLightCS;
public:
void updateDynamicLights();
int getDynamicLight(int x, int y, int z);
private:
// 4J - Calendar is now static
// Calendar *calendar;

View file

@ -160,6 +160,10 @@ int Region::getLightColor(int x, int y, int z, int emitt, int tileId/*=-1*/)
{
int s = getBrightnessPropagate(LightLayer::Sky, x, y, z, tileId);
int b = getBrightnessPropagate(LightLayer::Block, x, y, z, tileId);
if (level) {
int dyn = level->getDynamicLight(x, y, z);
if (dyn > b) b = dyn;
}
if (b < emitt) b = emitt;
return s << 20 | b << 4;
}