diff --git a/src/components/Sky.tsx b/src/components/Sky.tsx index 97639e4b..d75a7835 100644 --- a/src/components/Sky.tsx +++ b/src/components/Sky.tsx @@ -298,6 +298,157 @@ export function SkyBox({ ); } +/** + * Solid color sky component for when useSkyTextures = 0. + * Renders SkySolidColor (ignoring alpha) with fog at the horizon. + * Uses the same fog logic as SkyBoxTexture for consistency. + */ +function SolidColorSky({ + skyColor, + fogColor, + fogState, +}: { + skyColor: Color; + fogColor?: Color; + fogState?: FogState; +}) { + const { camera } = useThree(); + + const enableFog = !!fogColor; + + const inverseProjectionMatrix = useMemo(() => { + return camera.projectionMatrixInverse; + }, [camera]); + + const fogVolumeData = useMemo( + () => + fogState ? packFogVolumeData(fogState.fogVolumes) : new Float32Array(12), + [fogState], + ); + + const horizonFogHeight = useMemo(() => { + if (!fogState) return 0.18; + const mRadius = fogState.visibleDistance * 0.95; + const skyBoxPtX = mRadius / Math.sqrt(3); + return HORIZON_FOG_HEIGHT / Math.sqrt(skyBoxPtX * skyBoxPtX + HORIZON_FOG_HEIGHT * HORIZON_FOG_HEIGHT); + }, [fogState]); + + return ( + + + + + + = volMinH && cameraHeight <= volMaxH) { + float rayInfluence; + if (direction.y >= 0.0) { + rayInfluence = 1.0 - smoothstep(0.0, 0.3, direction.y); + } else { + rayInfluence = 1.0; + } + volumeFogInfluence += rayInfluence * volPct; + } + } + + // Base fog factor from view direction + float baseFogFactor; + if (direction.y <= 0.0) { + baseFogFactor = 1.0; + } else if (direction.y >= horizonFogHeight) { + baseFogFactor = 0.0; + } else { + float t = direction.y / horizonFogHeight; + baseFogFactor = (1.0 - t) * (1.0 - t); + } + + // Combine base fog with volume fog influence + float finalFogFactor = min(1.0, baseFogFactor + volumeFogInfluence * 0.5); + + finalColor = mix(skyColor, fogColor, finalFogFactor); + } else { + finalColor = skyColor; + } + + gl_FragColor = vec4(linearToSRGB(finalColor), 1.0); + } + `} + depthWrite={false} + depthTest={false} + /> + + ); +} + /** * Get fog near/far parameters for the distance-based haze. * @@ -448,6 +599,9 @@ export function Sky({ object }: { object: TorqueObject }) { }; }, [scene, gl, hasFogParams, effectiveFogColor, skyColor]); + // Get linear sky solid color for the solid color sky shader + const linearSkySolidColor = skySolidColor?.[1]; + return ( <> {materialList && useSkyTextures ? ( @@ -460,6 +614,13 @@ export function Sky({ object }: { object: TorqueObject }) { fogState={hasFogParams ? fogState : undefined} /> + ) : linearSkySolidColor ? ( + /* When useSkyTextures = 0, render solid color sky with SkySolidColor */ + ) : null} {/* Cloud layers render independently of skybox textures */}