feat(environment): add adaptive atmospheric fog
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
import { useMemo } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import * as THREE from "three";
|
||||
import {
|
||||
GAME_SCENE_FALLBACK_BACKGROUND_COLOR,
|
||||
GAME_SCENE_FALLBACK_SKY_MODEL_PATH,
|
||||
@@ -6,24 +9,46 @@ import {
|
||||
GAME_SCENE_SKY_MODEL_SCALE,
|
||||
PHYSICS_SCENE_BACKGROUND_COLOR,
|
||||
} from "@/data/world/environmentConfig";
|
||||
import { FOG_CONFIG } from "@/data/world/fogConfig";
|
||||
import { FOG_CONFIG, FOG_LIGHTING_COLOR_MIX } from "@/data/world/fogConfig";
|
||||
import { useCameraMode } from "@/hooks/debug/useCameraMode";
|
||||
import { useSceneMode } from "@/hooks/debug/useSceneMode";
|
||||
import { useFogSettings } from "@/hooks/world/useFogSettings";
|
||||
import {
|
||||
isMapModelVisible,
|
||||
useMapPerformanceStore,
|
||||
} from "@/managers/stores/useMapPerformanceStore";
|
||||
import { SkyModel } from "@/components/three/world/SkyModel";
|
||||
import { useDebugStore } from "@/hooks/debug/useDebugStore";
|
||||
import { LIGHTING_STATE } from "@/world/lightingState";
|
||||
|
||||
const tempSunFogColor = new THREE.Color();
|
||||
|
||||
function getLightingFogColor(target: THREE.Color): THREE.Color {
|
||||
target.set(LIGHTING_STATE.ambientColor);
|
||||
target.multiplyScalar(FOG_LIGHTING_COLOR_MIX.ambient);
|
||||
tempSunFogColor.set(LIGHTING_STATE.sunColor);
|
||||
target.add(tempSunFogColor.multiplyScalar(FOG_LIGHTING_COLOR_MIX.sun));
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
export function Environment(): React.JSX.Element {
|
||||
const cameraMode = useCameraMode();
|
||||
const sceneMode = useSceneMode();
|
||||
const fog = useFogSettings();
|
||||
const fogEnabled = useDebugStore((debug) => debug.getFogEnabled());
|
||||
const groups = useMapPerformanceStore((state) => state.groups);
|
||||
const models = useMapPerformanceStore((state) => state.models);
|
||||
const scene = useThree((state) => state.scene);
|
||||
const fogColor = useMemo(() => getLightingFogColor(new THREE.Color()), []);
|
||||
const showSky = isMapModelVisible("sky", { groups, models });
|
||||
|
||||
useFrame(() => {
|
||||
if (!scene.fog) return;
|
||||
|
||||
getLightingFogColor(scene.fog.color);
|
||||
});
|
||||
|
||||
if (sceneMode === "physics") {
|
||||
return (
|
||||
<color attach="background" args={[PHYSICS_SCENE_BACKGROUND_COLOR]} />
|
||||
@@ -35,11 +60,16 @@ export function Environment(): React.JSX.Element {
|
||||
{FOG_CONFIG.enabled &&
|
||||
fogEnabled &&
|
||||
sceneMode === "game" &&
|
||||
cameraMode === "player" ? (
|
||||
<fog
|
||||
attach="fog"
|
||||
args={[FOG_CONFIG.color, FOG_CONFIG.near, FOG_CONFIG.far]}
|
||||
/>
|
||||
cameraMode === "player" &&
|
||||
fog.mode === "linear" ? (
|
||||
<fog attach="fog" args={[fogColor, fog.near, fog.far]} />
|
||||
) : null}
|
||||
{FOG_CONFIG.enabled &&
|
||||
fogEnabled &&
|
||||
sceneMode === "game" &&
|
||||
cameraMode === "player" &&
|
||||
fog.mode === "exp2" ? (
|
||||
<fogExp2 attach="fog" args={[fogColor, fog.density]} />
|
||||
) : null}
|
||||
{showSky ? (
|
||||
<SkyModel
|
||||
|
||||
+1
-13
@@ -5,7 +5,6 @@ import {
|
||||
AMBIENT_INTENSITY_MAX,
|
||||
AMBIENT_INTENSITY_MIN,
|
||||
AMBIENT_INTENSITY_STEP,
|
||||
LIGHTING_DEFAULTS,
|
||||
SUN_INTENSITY_MAX,
|
||||
SUN_INTENSITY_MIN,
|
||||
SUN_INTENSITY_STEP,
|
||||
@@ -20,24 +19,13 @@ import {
|
||||
SUN_Z_STEP,
|
||||
} from "@/data/world/lightingConfig";
|
||||
import { useDebugFolder } from "@/hooks/debug/useDebugFolder";
|
||||
import { LIGHTING_STATE } from "@/world/lightingState";
|
||||
|
||||
const SHADOW_MAP_SIZE = 2048;
|
||||
const SHADOW_CAMERA_SIZE = 170;
|
||||
const SHADOW_CAMERA_NEAR = 0.5;
|
||||
const SHADOW_CAMERA_FAR = 300;
|
||||
|
||||
type LightingState = {
|
||||
ambientColor: string;
|
||||
ambientIntensity: number;
|
||||
sunColor: string;
|
||||
sunIntensity: number;
|
||||
sunX: number;
|
||||
sunY: number;
|
||||
sunZ: number;
|
||||
};
|
||||
|
||||
const LIGHTING_STATE: LightingState = { ...LIGHTING_DEFAULTS };
|
||||
|
||||
export function Lighting(): React.JSX.Element {
|
||||
const ambient = useRef<AmbientLight>(null);
|
||||
const sun = useRef<DirectionalLight>(null);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { LIGHTING_DEFAULTS } from "@/data/world/lightingConfig";
|
||||
|
||||
export interface LightingState {
|
||||
ambientColor: string;
|
||||
ambientIntensity: number;
|
||||
sunColor: string;
|
||||
sunIntensity: number;
|
||||
sunX: number;
|
||||
sunY: number;
|
||||
sunZ: number;
|
||||
}
|
||||
|
||||
export const LIGHTING_STATE: LightingState = { ...LIGHTING_DEFAULTS };
|
||||
@@ -44,8 +44,10 @@ export function WaterSurface({
|
||||
uOpacity: { value: WATER_SHADER_CONFIG.opacity },
|
||||
uDeepOpacity: { value: WATER_SHADER_CONFIG.deepOpacity },
|
||||
uFogEnabled: { value: 0 },
|
||||
uFogMode: { value: 0 },
|
||||
uFogNear: { value: FOG_CONFIG.near },
|
||||
uFogFar: { value: FOG_CONFIG.far },
|
||||
uFogDensity: { value: FOG_CONFIG.density },
|
||||
uFogColor: { value: new THREE.Color(FOG_CONFIG.color) },
|
||||
}),
|
||||
[],
|
||||
@@ -61,8 +63,10 @@ export function WaterSurface({
|
||||
uFlowX,
|
||||
uFlowZ,
|
||||
uFogColor,
|
||||
uFogDensity,
|
||||
uFogEnabled,
|
||||
uFogFar,
|
||||
uFogMode,
|
||||
uFogNear,
|
||||
uNoiseScale,
|
||||
uTime,
|
||||
@@ -77,9 +81,15 @@ export function WaterSurface({
|
||||
|
||||
if (scene.fog instanceof THREE.Fog) {
|
||||
if (uFogEnabled) uFogEnabled.value = 1;
|
||||
if (uFogMode) uFogMode.value = 0;
|
||||
if (uFogNear) uFogNear.value = scene.fog.near;
|
||||
if (uFogFar) uFogFar.value = scene.fog.far;
|
||||
if (uFogColor) uFogColor.value.copy(scene.fog.color);
|
||||
} else if (scene.fog instanceof THREE.FogExp2) {
|
||||
if (uFogEnabled) uFogEnabled.value = 1;
|
||||
if (uFogMode) uFogMode.value = 1;
|
||||
if (uFogDensity) uFogDensity.value = scene.fog.density;
|
||||
if (uFogColor) uFogColor.value.copy(scene.fog.color);
|
||||
} else if (uFogEnabled) {
|
||||
uFogEnabled.value = 0;
|
||||
}
|
||||
|
||||
@@ -33,8 +33,10 @@ export const WATER_FRAGMENT_SHADER = /* glsl */ `
|
||||
uniform float uOpacity;
|
||||
uniform float uDeepOpacity;
|
||||
uniform float uFogEnabled;
|
||||
uniform float uFogMode;
|
||||
uniform float uFogNear;
|
||||
uniform float uFogFar;
|
||||
uniform float uFogDensity;
|
||||
uniform vec3 uFogColor;
|
||||
|
||||
varying vec2 vUv;
|
||||
@@ -152,6 +154,12 @@ export const WATER_FRAGMENT_SHADER = /* glsl */ `
|
||||
if (uFogEnabled > 0.5) {
|
||||
float fogDistance = distance(cameraPosition, vWorldPosition);
|
||||
float fogFactor = smoothstep(uFogNear, uFogFar, fogDistance);
|
||||
|
||||
if (uFogMode > 0.5) {
|
||||
fogFactor = 1.0 - exp(-uFogDensity * uFogDensity * fogDistance * fogDistance);
|
||||
}
|
||||
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
color = mix(color, uFogColor, fogFactor);
|
||||
alpha *= 1.0 - fogFactor;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user