Feat/map-environment #6
@@ -1,17 +1,39 @@
|
|||||||
import { TERRAIN_COLORS } from "@/data/world/terrainConfig";
|
import { TERRAIN_COLORS } from "@/data/world/terrainConfig";
|
||||||
|
|
||||||
|
export type FogMode = "linear" | "exp2";
|
||||||
|
|
||||||
export const FOG_CONFIG = {
|
export const FOG_CONFIG = {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
color: "#dce8df",
|
mode: "exp2" as FogMode,
|
||||||
near: 38,
|
color: "#dfe7d8",
|
||||||
far: 45,
|
near: 32,
|
||||||
|
far: 48,
|
||||||
|
density: 0.032,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const FOG_LIGHTING_COLOR_MIX = {
|
||||||
|
ambient: 0.3,
|
||||||
|
sun: 0.7,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FOG_BOUNDS = {
|
||||||
|
near: { min: 0, max: 100, step: 1 },
|
||||||
|
far: { min: 1, max: 160, step: 1 },
|
||||||
|
density: { min: 0.001, max: 0.05, step: 0.001 },
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface FogState {
|
||||||
|
density: number;
|
||||||
|
far: number;
|
||||||
|
mode: FogMode;
|
||||||
|
near: number;
|
||||||
|
}
|
||||||
|
|
||||||
export const CHUNK_CONFIG = {
|
export const CHUNK_CONFIG = {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
chunkSize: 35,
|
chunkSize: 35,
|
||||||
loadRadius: 45,
|
loadRadius: 65,
|
||||||
unloadRadius: 45,
|
unloadRadius: 75,
|
||||||
updateInterval: 350,
|
updateInterval: 350,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { CLOUD_BOUNDS } from "@/data/world/cloudConfig";
|
import { CLOUD_BOUNDS } from "@/data/world/cloudConfig";
|
||||||
|
import { FOG_BOUNDS, type FogMode } from "@/data/world/fogConfig";
|
||||||
import { WIND_BOUNDS } from "@/data/world/windConfig";
|
import { WIND_BOUNDS } from "@/data/world/windConfig";
|
||||||
import { useDebugFolder } from "@/hooks/debug/useDebugFolder";
|
import { useDebugFolder } from "@/hooks/debug/useDebugFolder";
|
||||||
import { useWorldSettingsStore } from "@/managers/stores/useWorldSettingsStore";
|
import { useWorldSettingsStore } from "@/managers/stores/useWorldSettingsStore";
|
||||||
|
import { Debug } from "@/utils/debug/Debug";
|
||||||
|
|
||||||
export function useEnvironmentDebug(): void {
|
export function useEnvironmentDebug(): void {
|
||||||
useDebugFolder("Dynamic Wind", (folder) => {
|
useDebugFolder("Dynamic Wind", (folder) => {
|
||||||
@@ -49,13 +51,39 @@ export function useEnvironmentDebug(): void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useDebugFolder("Environment", (folder) => {
|
useDebugFolder("Environment", (folder) => {
|
||||||
const { clouds, graphics, setClouds, setDynamicClouds } =
|
Debug.getInstance().addFogControl(folder);
|
||||||
|
|
||||||
|
const { clouds, fog, graphics, setClouds, setDynamicClouds, setFog } =
|
||||||
useWorldSettingsStore.getState();
|
useWorldSettingsStore.getState();
|
||||||
const controls = {
|
const controls = {
|
||||||
...clouds,
|
...clouds,
|
||||||
|
...fog,
|
||||||
dynamicClouds: graphics.dynamicClouds,
|
dynamicClouds: graphics.dynamicClouds,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
folder
|
||||||
|
.add(controls, "mode", { Linear: "linear", Exp2: "exp2" })
|
||||||
|
.name("Fog mode")
|
||||||
|
.onChange((mode: FogMode) => setFog({ mode }));
|
||||||
|
|
||||||
|
folder
|
||||||
|
.add(controls, "near", FOG_BOUNDS.near.min, FOG_BOUNDS.near.max)
|
||||||
|
.step(FOG_BOUNDS.near.step)
|
||||||
|
.name("Fog near")
|
||||||
|
.onChange((near: number) => setFog({ near }));
|
||||||
|
|
||||||
|
folder
|
||||||
|
.add(controls, "far", FOG_BOUNDS.far.min, FOG_BOUNDS.far.max)
|
||||||
|
.step(FOG_BOUNDS.far.step)
|
||||||
|
.name("Fog far")
|
||||||
|
.onChange((far: number) => setFog({ far }));
|
||||||
|
|
||||||
|
folder
|
||||||
|
.add(controls, "density", FOG_BOUNDS.density.min, FOG_BOUNDS.density.max)
|
||||||
|
.step(FOG_BOUNDS.density.step)
|
||||||
|
.name("Fog density")
|
||||||
|
.onChange((density: number) => setFog({ density }));
|
||||||
|
|
||||||
folder
|
folder
|
||||||
.add(controls, "dynamicClouds")
|
.add(controls, "dynamicClouds")
|
||||||
.name("Clouds")
|
.name("Clouds")
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { useDebugFolder } from "@/hooks/debug/useDebugFolder";
|
import { useDebugFolder } from "@/hooks/debug/useDebugFolder";
|
||||||
import { Debug } from "@/utils/debug/Debug";
|
|
||||||
import {
|
import {
|
||||||
MAP_PERFORMANCE_GROUP_NAMES,
|
MAP_PERFORMANCE_GROUP_NAMES,
|
||||||
MAP_PERFORMANCE_MODEL_NAMES,
|
MAP_PERFORMANCE_MODEL_NAMES,
|
||||||
@@ -16,8 +15,6 @@ function toLabel(value: string): string {
|
|||||||
|
|
||||||
export function useMapPerformanceDebug(): void {
|
export function useMapPerformanceDebug(): void {
|
||||||
useDebugFolder("Map", (folder) => {
|
useDebugFolder("Map", (folder) => {
|
||||||
Debug.getInstance().addFogControl(folder);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
groups,
|
groups,
|
||||||
models,
|
models,
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { useWorldSettingsStore } from "@/managers/stores/useWorldSettingsStore";
|
||||||
|
import type { FogState } from "@/data/world/fogConfig";
|
||||||
|
|
||||||
|
export function useFogSettings(): FogState {
|
||||||
|
return useWorldSettingsStore((state) => state.fog);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useSetFogSettings(): (fog: Partial<FogState>) => void {
|
||||||
|
return useWorldSettingsStore((state) => state.setFog);
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { CLOUD_DEFAULTS, type CloudState } from "@/data/world/cloudConfig";
|
import { CLOUD_DEFAULTS, type CloudState } from "@/data/world/cloudConfig";
|
||||||
|
import { FOG_CONFIG, type FogState } from "@/data/world/fogConfig";
|
||||||
import { WIND_DEFAULTS, type WindState } from "@/data/world/windConfig";
|
import { WIND_DEFAULTS, type WindState } from "@/data/world/windConfig";
|
||||||
import {
|
import {
|
||||||
GRAPHICS_DEFAULTS,
|
GRAPHICS_DEFAULTS,
|
||||||
@@ -8,12 +9,14 @@ import {
|
|||||||
|
|
||||||
interface WorldSettingsState {
|
interface WorldSettingsState {
|
||||||
clouds: CloudState;
|
clouds: CloudState;
|
||||||
|
fog: FogState;
|
||||||
wind: WindState;
|
wind: WindState;
|
||||||
graphics: GraphicsState;
|
graphics: GraphicsState;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WorldSettingsActions {
|
interface WorldSettingsActions {
|
||||||
setClouds: (clouds: Partial<CloudState>) => void;
|
setClouds: (clouds: Partial<CloudState>) => void;
|
||||||
|
setFog: (fog: Partial<FogState>) => void;
|
||||||
setWind: (wind: Partial<WindState>) => void;
|
setWind: (wind: Partial<WindState>) => void;
|
||||||
setWindSpeed: (speed: number) => void;
|
setWindSpeed: (speed: number) => void;
|
||||||
setWindDirection: (direction: number) => void;
|
setWindDirection: (direction: number) => void;
|
||||||
@@ -31,6 +34,12 @@ type WorldSettingsStore = WorldSettingsState & WorldSettingsActions;
|
|||||||
|
|
||||||
const DEFAULT_STATE: WorldSettingsState = {
|
const DEFAULT_STATE: WorldSettingsState = {
|
||||||
clouds: { ...CLOUD_DEFAULTS },
|
clouds: { ...CLOUD_DEFAULTS },
|
||||||
|
fog: {
|
||||||
|
density: FOG_CONFIG.density,
|
||||||
|
far: FOG_CONFIG.far,
|
||||||
|
mode: FOG_CONFIG.mode,
|
||||||
|
near: FOG_CONFIG.near,
|
||||||
|
},
|
||||||
wind: { ...WIND_DEFAULTS },
|
wind: { ...WIND_DEFAULTS },
|
||||||
graphics: { ...GRAPHICS_DEFAULTS },
|
graphics: { ...GRAPHICS_DEFAULTS },
|
||||||
};
|
};
|
||||||
@@ -43,6 +52,11 @@ export const useWorldSettingsStore = create<WorldSettingsStore>()((set) => ({
|
|||||||
clouds: { ...state.clouds, ...cloudsUpdate },
|
clouds: { ...state.clouds, ...cloudsUpdate },
|
||||||
})),
|
})),
|
||||||
|
|
||||||
|
setFog: (fogUpdate) =>
|
||||||
|
set((state) => ({
|
||||||
|
fog: { ...state.fog, ...fogUpdate },
|
||||||
|
})),
|
||||||
|
|
||||||
setWind: (windUpdate) =>
|
setWind: (windUpdate) =>
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
wind: { ...state.wind, ...windUpdate },
|
wind: { ...state.wind, ...windUpdate },
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
|
import * as THREE from "three";
|
||||||
import {
|
import {
|
||||||
GAME_SCENE_FALLBACK_BACKGROUND_COLOR,
|
GAME_SCENE_FALLBACK_BACKGROUND_COLOR,
|
||||||
GAME_SCENE_FALLBACK_SKY_MODEL_PATH,
|
GAME_SCENE_FALLBACK_SKY_MODEL_PATH,
|
||||||
@@ -6,24 +9,46 @@ import {
|
|||||||
GAME_SCENE_SKY_MODEL_SCALE,
|
GAME_SCENE_SKY_MODEL_SCALE,
|
||||||
PHYSICS_SCENE_BACKGROUND_COLOR,
|
PHYSICS_SCENE_BACKGROUND_COLOR,
|
||||||
} from "@/data/world/environmentConfig";
|
} 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 { useCameraMode } from "@/hooks/debug/useCameraMode";
|
||||||
import { useSceneMode } from "@/hooks/debug/useSceneMode";
|
import { useSceneMode } from "@/hooks/debug/useSceneMode";
|
||||||
|
import { useFogSettings } from "@/hooks/world/useFogSettings";
|
||||||
import {
|
import {
|
||||||
isMapModelVisible,
|
isMapModelVisible,
|
||||||
useMapPerformanceStore,
|
useMapPerformanceStore,
|
||||||
} from "@/managers/stores/useMapPerformanceStore";
|
} from "@/managers/stores/useMapPerformanceStore";
|
||||||
import { SkyModel } from "@/components/three/world/SkyModel";
|
import { SkyModel } from "@/components/three/world/SkyModel";
|
||||||
import { useDebugStore } from "@/hooks/debug/useDebugStore";
|
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 {
|
export function Environment(): React.JSX.Element {
|
||||||
const cameraMode = useCameraMode();
|
const cameraMode = useCameraMode();
|
||||||
const sceneMode = useSceneMode();
|
const sceneMode = useSceneMode();
|
||||||
|
const fog = useFogSettings();
|
||||||
const fogEnabled = useDebugStore((debug) => debug.getFogEnabled());
|
const fogEnabled = useDebugStore((debug) => debug.getFogEnabled());
|
||||||
const groups = useMapPerformanceStore((state) => state.groups);
|
const groups = useMapPerformanceStore((state) => state.groups);
|
||||||
const models = useMapPerformanceStore((state) => state.models);
|
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 });
|
const showSky = isMapModelVisible("sky", { groups, models });
|
||||||
|
|
||||||
|
useFrame(() => {
|
||||||
|
if (!scene.fog) return;
|
||||||
|
|
||||||
|
getLightingFogColor(scene.fog.color);
|
||||||
|
});
|
||||||
|
|
||||||
if (sceneMode === "physics") {
|
if (sceneMode === "physics") {
|
||||||
return (
|
return (
|
||||||
<color attach="background" args={[PHYSICS_SCENE_BACKGROUND_COLOR]} />
|
<color attach="background" args={[PHYSICS_SCENE_BACKGROUND_COLOR]} />
|
||||||
@@ -35,11 +60,16 @@ export function Environment(): React.JSX.Element {
|
|||||||
{FOG_CONFIG.enabled &&
|
{FOG_CONFIG.enabled &&
|
||||||
fogEnabled &&
|
fogEnabled &&
|
||||||
sceneMode === "game" &&
|
sceneMode === "game" &&
|
||||||
cameraMode === "player" ? (
|
cameraMode === "player" &&
|
||||||
<fog
|
fog.mode === "linear" ? (
|
||||||
attach="fog"
|
<fog attach="fog" args={[fogColor, fog.near, fog.far]} />
|
||||||
args={[FOG_CONFIG.color, FOG_CONFIG.near, FOG_CONFIG.far]}
|
) : null}
|
||||||
/>
|
{FOG_CONFIG.enabled &&
|
||||||
|
fogEnabled &&
|
||||||
|
sceneMode === "game" &&
|
||||||
|
cameraMode === "player" &&
|
||||||
|
fog.mode === "exp2" ? (
|
||||||
|
<fogExp2 attach="fog" args={[fogColor, fog.density]} />
|
||||||
) : null}
|
) : null}
|
||||||
{showSky ? (
|
{showSky ? (
|
||||||
<SkyModel
|
<SkyModel
|
||||||
|
|||||||
+1
-13
@@ -5,7 +5,6 @@ import {
|
|||||||
AMBIENT_INTENSITY_MAX,
|
AMBIENT_INTENSITY_MAX,
|
||||||
AMBIENT_INTENSITY_MIN,
|
AMBIENT_INTENSITY_MIN,
|
||||||
AMBIENT_INTENSITY_STEP,
|
AMBIENT_INTENSITY_STEP,
|
||||||
LIGHTING_DEFAULTS,
|
|
||||||
SUN_INTENSITY_MAX,
|
SUN_INTENSITY_MAX,
|
||||||
SUN_INTENSITY_MIN,
|
SUN_INTENSITY_MIN,
|
||||||
SUN_INTENSITY_STEP,
|
SUN_INTENSITY_STEP,
|
||||||
@@ -20,24 +19,13 @@ import {
|
|||||||
SUN_Z_STEP,
|
SUN_Z_STEP,
|
||||||
} from "@/data/world/lightingConfig";
|
} from "@/data/world/lightingConfig";
|
||||||
import { useDebugFolder } from "@/hooks/debug/useDebugFolder";
|
import { useDebugFolder } from "@/hooks/debug/useDebugFolder";
|
||||||
|
import { LIGHTING_STATE } from "@/world/lightingState";
|
||||||
|
|
||||||
const SHADOW_MAP_SIZE = 2048;
|
const SHADOW_MAP_SIZE = 2048;
|
||||||
const SHADOW_CAMERA_SIZE = 170;
|
const SHADOW_CAMERA_SIZE = 170;
|
||||||
const SHADOW_CAMERA_NEAR = 0.5;
|
const SHADOW_CAMERA_NEAR = 0.5;
|
||||||
const SHADOW_CAMERA_FAR = 300;
|
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 {
|
export function Lighting(): React.JSX.Element {
|
||||||
const ambient = useRef<AmbientLight>(null);
|
const ambient = useRef<AmbientLight>(null);
|
||||||
const sun = useRef<DirectionalLight>(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 },
|
uOpacity: { value: WATER_SHADER_CONFIG.opacity },
|
||||||
uDeepOpacity: { value: WATER_SHADER_CONFIG.deepOpacity },
|
uDeepOpacity: { value: WATER_SHADER_CONFIG.deepOpacity },
|
||||||
uFogEnabled: { value: 0 },
|
uFogEnabled: { value: 0 },
|
||||||
|
uFogMode: { value: 0 },
|
||||||
uFogNear: { value: FOG_CONFIG.near },
|
uFogNear: { value: FOG_CONFIG.near },
|
||||||
uFogFar: { value: FOG_CONFIG.far },
|
uFogFar: { value: FOG_CONFIG.far },
|
||||||
|
uFogDensity: { value: FOG_CONFIG.density },
|
||||||
uFogColor: { value: new THREE.Color(FOG_CONFIG.color) },
|
uFogColor: { value: new THREE.Color(FOG_CONFIG.color) },
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
@@ -61,8 +63,10 @@ export function WaterSurface({
|
|||||||
uFlowX,
|
uFlowX,
|
||||||
uFlowZ,
|
uFlowZ,
|
||||||
uFogColor,
|
uFogColor,
|
||||||
|
uFogDensity,
|
||||||
uFogEnabled,
|
uFogEnabled,
|
||||||
uFogFar,
|
uFogFar,
|
||||||
|
uFogMode,
|
||||||
uFogNear,
|
uFogNear,
|
||||||
uNoiseScale,
|
uNoiseScale,
|
||||||
uTime,
|
uTime,
|
||||||
@@ -77,9 +81,15 @@ export function WaterSurface({
|
|||||||
|
|
||||||
if (scene.fog instanceof THREE.Fog) {
|
if (scene.fog instanceof THREE.Fog) {
|
||||||
if (uFogEnabled) uFogEnabled.value = 1;
|
if (uFogEnabled) uFogEnabled.value = 1;
|
||||||
|
if (uFogMode) uFogMode.value = 0;
|
||||||
if (uFogNear) uFogNear.value = scene.fog.near;
|
if (uFogNear) uFogNear.value = scene.fog.near;
|
||||||
if (uFogFar) uFogFar.value = scene.fog.far;
|
if (uFogFar) uFogFar.value = scene.fog.far;
|
||||||
if (uFogColor) uFogColor.value.copy(scene.fog.color);
|
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) {
|
} else if (uFogEnabled) {
|
||||||
uFogEnabled.value = 0;
|
uFogEnabled.value = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ export const WATER_FRAGMENT_SHADER = /* glsl */ `
|
|||||||
uniform float uOpacity;
|
uniform float uOpacity;
|
||||||
uniform float uDeepOpacity;
|
uniform float uDeepOpacity;
|
||||||
uniform float uFogEnabled;
|
uniform float uFogEnabled;
|
||||||
|
uniform float uFogMode;
|
||||||
uniform float uFogNear;
|
uniform float uFogNear;
|
||||||
uniform float uFogFar;
|
uniform float uFogFar;
|
||||||
|
uniform float uFogDensity;
|
||||||
uniform vec3 uFogColor;
|
uniform vec3 uFogColor;
|
||||||
|
|
||||||
varying vec2 vUv;
|
varying vec2 vUv;
|
||||||
@@ -152,6 +154,12 @@ export const WATER_FRAGMENT_SHADER = /* glsl */ `
|
|||||||
if (uFogEnabled > 0.5) {
|
if (uFogEnabled > 0.5) {
|
||||||
float fogDistance = distance(cameraPosition, vWorldPosition);
|
float fogDistance = distance(cameraPosition, vWorldPosition);
|
||||||
float fogFactor = smoothstep(uFogNear, uFogFar, fogDistance);
|
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);
|
color = mix(color, uFogColor, fogFactor);
|
||||||
alpha *= 1.0 - fogFactor;
|
alpha *= 1.0 - fogFactor;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user