Fix WMO shadow receiving and enable shadows by default

Remove isInterior restriction from WMO shadow sampling so city
buildings (flagged as interior groups) correctly receive shadows.
Apply shadow to interior-lit surfaces. Enable shadows by default
and persist the setting across sessions.
This commit is contained in:
Kelsi 2026-02-23 08:40:16 -08:00
parent c3ed915649
commit 0a1e240831
5 changed files with 27 additions and 22 deletions

View file

@ -152,11 +152,29 @@ void main() {
vec3 result;
// Sample shadow map for all non-window WMO surfaces
float shadow = 1.0;
if (shadowParams.x > 0.5) {
vec3 ldir = normalize(-lightDir.xyz);
float normalOffset = SHADOW_TEXEL * 2.0 * (1.0 - abs(dot(norm, ldir)));
vec3 biasedPos = FragPos + norm * normalOffset;
vec4 lsPos = lightSpaceMatrix * vec4(biasedPos, 1.0);
vec3 proj = lsPos.xyz / lsPos.w;
proj.xy = proj.xy * 0.5 + 0.5;
if (proj.x >= 0.0 && proj.x <= 1.0 &&
proj.y >= 0.0 && proj.y <= 1.0 &&
proj.z >= 0.0 && proj.z <= 1.0) {
float bias = max(0.0005 * (1.0 - dot(norm, ldir)), 0.00005);
shadow = sampleShadowPCF(uShadowMap, vec3(proj.xy, proj.z - bias));
}
shadow = mix(1.0, shadow, shadowParams.y);
}
if (unlit != 0) {
result = texColor.rgb;
result = texColor.rgb * shadow;
} else if (isInterior != 0) {
vec3 mocv = max(VertColor.rgb, vec3(0.5));
result = texColor.rgb * mocv;
result = texColor.rgb * mocv * shadow;
} else {
vec3 ldir = normalize(-lightDir.xyz);
float diff = max(dot(norm, ldir), 0.0);
@ -165,22 +183,6 @@ void main() {
vec3 halfDir = normalize(ldir + viewDir);
float spec = pow(max(dot(norm, halfDir), 0.0), 32.0) * specularIntensity;
float shadow = 1.0;
if (shadowParams.x > 0.5) {
float normalOffset = SHADOW_TEXEL * 2.0 * (1.0 - abs(dot(norm, ldir)));
vec3 biasedPos = FragPos + norm * normalOffset;
vec4 lsPos = lightSpaceMatrix * vec4(biasedPos, 1.0);
vec3 proj = lsPos.xyz / lsPos.w;
proj.xy = proj.xy * 0.5 + 0.5;
if (proj.x >= 0.0 && proj.x <= 1.0 &&
proj.y >= 0.0 && proj.y <= 1.0 &&
proj.z >= 0.0 && proj.z <= 1.0) {
float bias = max(0.0005 * (1.0 - dot(norm, ldir)), 0.00005);
shadow = sampleShadowPCF(uShadowMap, vec3(proj.xy, proj.z - bias));
}
shadow = mix(1.0, shadow, shadowParams.y);
}
result = ambientColor.rgb * texColor.rgb
+ shadow * (diff * lightColor.rgb * texColor.rgb + spec * lightColor.rgb);

Binary file not shown.

View file

@ -80,7 +80,7 @@ private:
bool pendingFullscreen = false;
bool pendingVsync = false;
int pendingResIndex = 0;
bool pendingShadows = false;
bool pendingShadows = true;
int pendingMasterVolume = 100;
int pendingMusicVolume = 30;
int pendingAmbientVolume = 100;

View file

@ -603,7 +603,8 @@ void Renderer::updatePerFrameUBO() {
}
}
currentFrameData.shadowParams = glm::vec4(shadowsEnabled ? 1.0f : 0.0f, 0.5f, 0.0f, 0.0f);
currentFrameData.lightSpaceMatrix = lightSpaceMatrix;
currentFrameData.shadowParams = glm::vec4(shadowsEnabled ? 1.0f : 0.0f, 0.8f, 0.0f, 0.0f);
// Player water ripple data: pack player XY into shadowParams.zw, ripple strength into fogParams.w
if (cameraController) {

View file

@ -5893,7 +5893,7 @@ void GameScreen::renderSettingsWindow() {
constexpr int kDefaultResH = 1080;
constexpr bool kDefaultFullscreen = false;
constexpr bool kDefaultVsync = true;
constexpr bool kDefaultShadows = false;
constexpr bool kDefaultShadows = true;
constexpr int kDefaultMusicVolume = 30;
constexpr float kDefaultMouseSensitivity = 0.2f;
constexpr bool kDefaultInvertMouse = false;
@ -5910,8 +5910,8 @@ void GameScreen::renderSettingsWindow() {
if (!settingsInit) {
pendingFullscreen = window->isFullscreen();
pendingVsync = window->isVsyncEnabled();
pendingShadows = renderer ? renderer->areShadowsEnabled() : true;
if (renderer) {
renderer->setShadowsEnabled(pendingShadows);
// Read non-volume settings from actual state (volumes come from saved settings)
if (auto* cameraController = renderer->getCameraController()) {
pendingMouseSensitivity = cameraController->getMouseSensitivity();
@ -7089,6 +7089,7 @@ void GameScreen::saveSettings() {
// Gameplay
out << "auto_loot=" << (pendingAutoLoot ? 1 : 0) << "\n";
out << "ground_clutter_density=" << pendingGroundClutterDensity << "\n";
out << "shadows=" << (pendingShadows ? 1 : 0) << "\n";
out << "antialiasing=" << pendingAntiAliasing << "\n";
out << "normal_mapping=" << (pendingNormalMapping ? 1 : 0) << "\n";
out << "normal_map_strength=" << pendingNormalMapStrength << "\n";
@ -7172,6 +7173,7 @@ void GameScreen::loadSettings() {
// Gameplay
else if (key == "auto_loot") pendingAutoLoot = (std::stoi(val) != 0);
else if (key == "ground_clutter_density") pendingGroundClutterDensity = std::clamp(std::stoi(val), 0, 150);
else if (key == "shadows") pendingShadows = (std::stoi(val) != 0);
else if (key == "antialiasing") pendingAntiAliasing = std::clamp(std::stoi(val), 0, 3);
else if (key == "normal_mapping") pendingNormalMapping = (std::stoi(val) != 0);
else if (key == "normal_map_strength") pendingNormalMapStrength = std::clamp(std::stof(val), 0.0f, 2.0f);