From 748d9db4f814b9492774b8d8c1f53ea32b1c1d05 Mon Sep 17 00:00:00 2001 From: lby Date: Wed, 28 Jun 2023 11:31:26 +0800 Subject: [PATCH] feat(web): visualizer supports shadow map (#524) --- web/src/beta/lib/core/Map/types/index.ts | 3 + web/src/beta/lib/core/engines/Cesium/hooks.ts | 62 ++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/web/src/beta/lib/core/Map/types/index.ts b/web/src/beta/lib/core/Map/types/index.ts index a9b3d58fe5..8b529b8258 100644 --- a/web/src/beta/lib/core/Map/types/index.ts +++ b/web/src/beta/lib/core/Map/types/index.ts @@ -288,6 +288,9 @@ export type SceneProperty = { ground_atmosphere?: boolean; sky_atmosphere?: boolean; shadows?: boolean; + shadowResolution?: 1024 | 2048 | 4096; + softShadow?: boolean; + shadowDarkness?: number; fog?: boolean; fog_density?: number; brightness_shift?: number; diff --git a/web/src/beta/lib/core/engines/Cesium/hooks.ts b/web/src/beta/lib/core/engines/Cesium/hooks.ts index 965a01b354..c9595eec9f 100644 --- a/web/src/beta/lib/core/engines/Cesium/hooks.ts +++ b/web/src/beta/lib/core/engines/Cesium/hooks.ts @@ -12,7 +12,7 @@ import { SunLight, DirectionalLight, } from "cesium"; -import type { Viewer as CesiumViewer } from "cesium"; +import type { Viewer as CesiumViewer, ShadowMap } from "cesium"; import CesiumDnD, { Context } from "cesium-dnd"; import { isEqual } from "lodash-es"; import { RefObject, useCallback, useEffect, useMemo, useRef } from "react"; @@ -132,6 +132,66 @@ export default ({ property?.light?.lightIntensity, ]); + // shadow map + type ShadowMapBias = { + polygonOffsetFactor: number; + polygonOffsetUnits: number; + normalOffsetScale: number; + normalShading: boolean; + normalShadingSmooth: number; + depthBias: number; + }; + + useEffect(() => { + const shadowMap = cesium?.current?.cesiumElement?.shadowMap as + | (ShadowMap & { + _terrainBias: ShadowMapBias; + _pointBias: ShadowMapBias; + _primitiveBias: ShadowMapBias; + }) + | undefined; + if (!shadowMap) return; + shadowMap.softShadows = property?.atmosphere?.softShadow ?? false; + shadowMap.darkness = property?.atmosphere?.shadowDarkness ?? 0.3; + shadowMap.size = property?.atmosphere?.shadowResolution ?? 2048; + shadowMap.fadingEnabled = true; + shadowMap.maximumDistance = 5000; + shadowMap.normalOffset = true; + + // bias + const defaultTerrainBias: ShadowMapBias = { + polygonOffsetFactor: 1.1, + polygonOffsetUnits: 4.0, + normalOffsetScale: 0.5, + normalShading: true, + normalShadingSmooth: 0.3, + depthBias: 0.0001, + }; + const defaultPrimitiveBias: ShadowMapBias = { + polygonOffsetFactor: 1.1, + polygonOffsetUnits: 4.0, + normalOffsetScale: 0.1 * 100, + normalShading: true, + normalShadingSmooth: 0.05, + depthBias: 0.00002 * 10, + }; + const defaultPointBias: ShadowMapBias = { + polygonOffsetFactor: 1.1, + polygonOffsetUnits: 4.0, + normalOffsetScale: 0.0, + normalShading: true, + normalShadingSmooth: 0.1, + depthBias: 0.0005, + }; + Object.assign(shadowMap._terrainBias, defaultTerrainBias); + Object.assign(shadowMap._primitiveBias, defaultPrimitiveBias); + Object.assign(shadowMap._pointBias, defaultPointBias); + }, [ + property?.atmosphere?.softShadow, + property?.atmosphere?.shadowDarkness, + property?.atmosphere?.shadowResolution, + ]); + useEffect(() => { engineAPI.changeSceneMode(property?.default?.sceneMode, 0); }, [property?.default?.sceneMode, engineAPI]);