Add advanced rendering settings to world configuration

This commit is contained in:
2026-04-02 20:41:17 +02:00
parent 736bca3c0f
commit 26c6af37e8

View File

@@ -2,6 +2,14 @@ import { DEFAULT_SUN_DIRECTION, type Vec3 } from "../core/vector";
export type WorldBackgroundMode = "solid" | "verticalGradient" | "image";
export const ADVANCED_RENDERING_SHADOW_MAP_SIZES = [512, 1024, 2048, 4096] as const;
export const ADVANCED_RENDERING_SHADOW_TYPES = ["basic", "pcf", "pcfSoft"] as const;
export const ADVANCED_RENDERING_TONE_MAPPING_MODES = ["none", "linear", "reinhard", "cineon", "acesFilmic"] as const;
export type AdvancedRenderingShadowMapSize = (typeof ADVANCED_RENDERING_SHADOW_MAP_SIZES)[number];
export type AdvancedRenderingShadowType = (typeof ADVANCED_RENDERING_SHADOW_TYPES)[number];
export type AdvancedRenderingToneMappingMode = (typeof ADVANCED_RENDERING_TONE_MAPPING_MODES)[number];
export interface WorldSolidBackgroundSettings {
mode: "solid";
colorHex: string;
@@ -35,15 +43,118 @@ export interface WorldSunLightSettings {
direction: Vec3;
}
export interface AdvancedRenderingShadowsSettings {
enabled: boolean;
mapSize: AdvancedRenderingShadowMapSize;
type: AdvancedRenderingShadowType;
bias: number;
}
export interface AdvancedRenderingAmbientOcclusionSettings {
enabled: boolean;
intensity: number;
radius: number;
samples: number;
}
export interface AdvancedRenderingBloomSettings {
enabled: boolean;
intensity: number;
threshold: number;
radius: number;
}
export interface AdvancedRenderingToneMappingSettings {
mode: AdvancedRenderingToneMappingMode;
exposure: number;
}
export interface AdvancedRenderingDepthOfFieldSettings {
enabled: boolean;
focusDistance: number;
focalLength: number;
bokehScale: number;
}
export interface AdvancedRenderingSettings {
enabled: boolean;
shadows: AdvancedRenderingShadowsSettings;
ambientOcclusion: AdvancedRenderingAmbientOcclusionSettings;
bloom: AdvancedRenderingBloomSettings;
toneMapping: AdvancedRenderingToneMappingSettings;
depthOfField: AdvancedRenderingDepthOfFieldSettings;
}
export interface WorldSettings {
background: WorldBackgroundSettings;
ambientLight: WorldAmbientLightSettings;
sunLight: WorldSunLightSettings;
advancedRendering: AdvancedRenderingSettings;
}
const DEFAULT_SOLID_BACKGROUND_COLOR = "#2f3947";
const DEFAULT_GRADIENT_TOP_COLOR = DEFAULT_SOLID_BACKGROUND_COLOR;
const DEFAULT_GRADIENT_BOTTOM_COLOR = "#141a22";
const DEFAULT_ADVANCED_RENDERING_SHADOW_MAP_SIZE: AdvancedRenderingShadowMapSize = 2048;
const DEFAULT_ADVANCED_RENDERING_SHADOW_TYPE: AdvancedRenderingShadowType = "pcfSoft";
const DEFAULT_ADVANCED_RENDERING_SHADOW_BIAS = -0.0005;
const DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_INTENSITY = 1;
const DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_RADIUS = 0.5;
const DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_SAMPLES = 8;
const DEFAULT_ADVANCED_RENDERING_BLOOM_INTENSITY = 0.75;
const DEFAULT_ADVANCED_RENDERING_BLOOM_THRESHOLD = 0.85;
const DEFAULT_ADVANCED_RENDERING_BLOOM_RADIUS = 0.35;
const DEFAULT_ADVANCED_RENDERING_TONE_MAPPING_MODE: AdvancedRenderingToneMappingMode = "acesFilmic";
const DEFAULT_ADVANCED_RENDERING_TONE_MAPPING_EXPOSURE = 1;
const DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_FOCUS_DISTANCE = 10;
const DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_FOCAL_LENGTH = 0.03;
const DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_BOKEH_SCALE = 1.5;
export function isAdvancedRenderingShadowMapSize(value: unknown): value is AdvancedRenderingShadowMapSize {
return ADVANCED_RENDERING_SHADOW_MAP_SIZES.includes(value as AdvancedRenderingShadowMapSize);
}
export function isAdvancedRenderingShadowType(value: unknown): value is AdvancedRenderingShadowType {
return ADVANCED_RENDERING_SHADOW_TYPES.includes(value as AdvancedRenderingShadowType);
}
export function isAdvancedRenderingToneMappingMode(value: unknown): value is AdvancedRenderingToneMappingMode {
return ADVANCED_RENDERING_TONE_MAPPING_MODES.includes(value as AdvancedRenderingToneMappingMode);
}
export function createDefaultAdvancedRenderingSettings(): AdvancedRenderingSettings {
return {
enabled: false,
shadows: {
enabled: false,
mapSize: DEFAULT_ADVANCED_RENDERING_SHADOW_MAP_SIZE,
type: DEFAULT_ADVANCED_RENDERING_SHADOW_TYPE,
bias: DEFAULT_ADVANCED_RENDERING_SHADOW_BIAS
},
ambientOcclusion: {
enabled: false,
intensity: DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_INTENSITY,
radius: DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_RADIUS,
samples: DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_SAMPLES
},
bloom: {
enabled: false,
intensity: DEFAULT_ADVANCED_RENDERING_BLOOM_INTENSITY,
threshold: DEFAULT_ADVANCED_RENDERING_BLOOM_THRESHOLD,
radius: DEFAULT_ADVANCED_RENDERING_BLOOM_RADIUS
},
toneMapping: {
mode: DEFAULT_ADVANCED_RENDERING_TONE_MAPPING_MODE,
exposure: DEFAULT_ADVANCED_RENDERING_TONE_MAPPING_EXPOSURE
},
depthOfField: {
enabled: false,
focusDistance: DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_FOCUS_DISTANCE,
focalLength: DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_FOCAL_LENGTH,
bokehScale: DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_BOKEH_SCALE
}
};
}
export function createDefaultWorldSettings(): WorldSettings {
return {
@@ -61,7 +172,8 @@ export function createDefaultWorldSettings(): WorldSettings {
direction: {
...DEFAULT_SUN_DIRECTION
}
}
},
advancedRendering: createDefaultAdvancedRenderingSettings()
};
}
@@ -107,6 +219,28 @@ export function cloneWorldSettings(world: WorldSettings): WorldSettings {
direction: {
...world.sunLight.direction
}
},
advancedRendering: cloneAdvancedRenderingSettings(world.advancedRendering)
};
}
export function cloneAdvancedRenderingSettings(settings: AdvancedRenderingSettings): AdvancedRenderingSettings {
return {
enabled: settings.enabled,
shadows: {
...settings.shadows
},
ambientOcclusion: {
...settings.ambientOcclusion
},
bloom: {
...settings.bloom
},
toneMapping: {
...settings.toneMapping
},
depthOfField: {
...settings.depthOfField
}
};
}
@@ -136,7 +270,32 @@ export function areWorldSettingsEqual(left: WorldSettings, right: WorldSettings)
left.sunLight.intensity === right.sunLight.intensity &&
left.sunLight.direction.x === right.sunLight.direction.x &&
left.sunLight.direction.y === right.sunLight.direction.y &&
left.sunLight.direction.z === right.sunLight.direction.z
left.sunLight.direction.z === right.sunLight.direction.z &&
areAdvancedRenderingSettingsEqual(left.advancedRendering, right.advancedRendering)
);
}
export function areAdvancedRenderingSettingsEqual(left: AdvancedRenderingSettings, right: AdvancedRenderingSettings): boolean {
return (
left.enabled === right.enabled &&
left.shadows.enabled === right.shadows.enabled &&
left.shadows.mapSize === right.shadows.mapSize &&
left.shadows.type === right.shadows.type &&
left.shadows.bias === right.shadows.bias &&
left.ambientOcclusion.enabled === right.ambientOcclusion.enabled &&
left.ambientOcclusion.intensity === right.ambientOcclusion.intensity &&
left.ambientOcclusion.radius === right.ambientOcclusion.radius &&
left.ambientOcclusion.samples === right.ambientOcclusion.samples &&
left.bloom.enabled === right.bloom.enabled &&
left.bloom.intensity === right.bloom.intensity &&
left.bloom.threshold === right.bloom.threshold &&
left.bloom.radius === right.bloom.radius &&
left.toneMapping.mode === right.toneMapping.mode &&
left.toneMapping.exposure === right.toneMapping.exposure &&
left.depthOfField.enabled === right.depthOfField.enabled &&
left.depthOfField.focusDistance === right.depthOfField.focusDistance &&
left.depthOfField.focalLength === right.depthOfField.focalLength &&
left.depthOfField.bokehScale === right.depthOfField.bokehScale
);
}