Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/components/game/hooks/usePostProcessing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,45 @@ export function usePostProcessing({

// Handle post-processing toggle
if (settings.postProcessingEnabled !== prevSettings.postProcessingEnabled) {
const fogOfWarNeeded = useGameSetupStore.getState().fogOfWar && !isSpectatorMode();

if (!settings.postProcessingEnabled) {
renderPipelineRef.current?.dispose();
renderPipelineRef.current = null;

// If fog of war is needed, create a minimal pipeline with only fog of war enabled
// Fog of war requires the post-processing pipeline for depth-based world reconstruction
if (fogOfWarNeeded && renderContextRef.current && sceneRef.current && cameraRef.current) {
renderPipelineRef.current = new RenderPipeline(
renderContextRef.current.renderer,
sceneRef.current,
cameraRef.current.camera,
{
// Disable all effects except fog of war
bloomEnabled: false,
aoEnabled: false,
ssrEnabled: false,
ssgiEnabled: false,
antiAliasingMode: 'off',
fxaaEnabled: false,
taaEnabled: false,
upscalingMode: 'off',
vignetteEnabled: false,
volumetricFogEnabled: false,
// Keep fog of war enabled with current settings
fogOfWarEnabled: true,
fogOfWarQuality: settings.fogOfWarQuality,
fogOfWarEdgeBlur: settings.fogOfWarEdgeBlur,
fogOfWarDesaturation: settings.fogOfWarDesaturation,
fogOfWarExploredDarkness: settings.fogOfWarExploredDarkness,
fogOfWarUnexploredDarkness: settings.fogOfWarUnexploredDarkness,
fogOfWarCloudSpeed: settings.fogOfWarCloudSpeed,
fogOfWarRimIntensity: settings.fogOfWarRimIntensity,
fogOfWarHeightInfluence: settings.fogOfWarHeightInfluence,
}
);
renderPipelineRef.current.setFogOfWarMapDimensions(mapRef.current.width, mapRef.current.height);
}
} else if (renderContextRef.current && sceneRef.current && cameraRef.current) {
renderPipelineRef.current = new RenderPipeline(
renderContextRef.current.renderer,
Expand Down
19 changes: 17 additions & 2 deletions src/rendering/tsl/effects/EffectPasses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -934,9 +934,24 @@ export function createFogOfWarPass(
const maxDist = min(surfaceDistance, uVolMaxDistance);
const stepSize = maxDist.div(uVolSteps);

// Base fog density from visibility (sampled ONCE at surface - no loop sampling)
// Sample visibility at a point along the ray (30% from camera to surface)
// This prevents the southward shift caused by sampling only at the surface,
// which with the RTS camera angle would bias fog toward unexplored areas
const volSamplePoint = uCameraPos.add(rayDir.mul(surfaceDistance.mul(0.3)));
const volVisionU = volSamplePoint.x.div(uMapDimensions.x);
const volVisionV = volSamplePoint.z.div(uMapDimensions.y);
const volVisionUV = clamp(vec2(volVisionU, volVisionV), 0.001, 0.999);
const volVisionSample = visionTextureNode.sample(volVisionUV);
const volExplored = volVisionSample.r;
const volVisible = volVisionSample.g;
const volIsVisible = smoothstep(float(0.4), float(0.6), volVisible);
const volIsExplored = smoothstep(float(0.4), float(0.6), volExplored);
const volIsUnexplored = float(1.0).sub(max(volIsVisible, volIsExplored));
const volExploredAmount = volIsExplored.mul(float(1.0).sub(volIsVisible));

// Base fog density from visibility sampled along the ray
// Unexplored = full fog, explored = partial, visible = none
const baseDensity = isUnexplored.add(exploredAmount.mul(0.4)).mul(uVolFogDensity);
const baseDensity = volIsUnexplored.add(volExploredAmount.mul(0.4)).mul(uVolFogDensity);

// Volumetric accumulation
const volTransmittance = float(1.0).toVar();
Expand Down
Loading