diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-21 20:12:44 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-21 20:12:44 +0800 |
| commit | 8d594b6a541c5ee2ab3ddf9fe870df790d0bb357 (patch) | |
| tree | f01c242ae826fb74add371bdb650f16603d433ad /src/SomhairlesDream.Frontend | |
| parent | 8a1e79e46605291234314bd1a02dcab7a8c9bdc1 (diff) | |
| download | somhairles-dream-fsharp-8d594b6a541c5ee2ab3ddf9fe870df790d0bb357.tar.gz | |
feat(detail): engineering detail pass on both models + PBR studio pipeline (ACES, env reflections, rim/bounce lights)
Diffstat (limited to 'src/SomhairlesDream.Frontend')
| -rw-r--r-- | src/SomhairlesDream.Frontend/App.fs | 18 | ||||
| -rw-r--r-- | src/SomhairlesDream.Frontend/Bindings.fs | 27 |
2 files changed, 44 insertions, 1 deletions
diff --git a/src/SomhairlesDream.Frontend/App.fs b/src/SomhairlesDream.Frontend/App.fs index dbb267c..315a0fc 100644 --- a/src/SomhairlesDream.Frontend/App.fs +++ b/src/SomhairlesDream.Frontend/App.fs @@ -241,17 +241,33 @@ let initializeView () = renderer.setPixelRatio(window.devicePixelRatio) renderer.setSize(width, height, false) + // PBR pipeline: ACES tone mapping + a procedural studio environment map + // so metalness/roughness from the GLB materials read as machined + // hardware instead of flat plastic. + setToneMappingACES renderer + setToneMappingExposure (renderer, 1.15) + setSRGBOutput renderer let scene = createScene() scene.background <- createColor("#11171a") + let envScene = createEnvScene() + let pmrem = createPMREMGenerator renderer + let envTexture = pmremFromScene (pmrem, envScene) + setSceneEnvironment (scene, envTexture) + setSceneEnvironmentIntensity (scene, 0.55) let camera = createPerspectiveCamera(34.0, width / height, 0.1, 100.0) camera.position.set(6.4, 4.6, 7.2) |> ignore camera.lookAt(0.0, 0.0, 0.0) let group = createGroup() scene.add(group) - scene.add(createAmbientLight("#f0e6c8", 1.9)) + scene.add(createAmbientLight("#f0e6c8", 0.55)) let keyLight = createDirectionalLight("#f2c76b", 2.8) keyLight.position.set(4.0, 7.0, 5.0) |> ignore scene.add(keyLight) + let rimLight = createDirectionalLight("#7fa8ff", 1.4) + rimLight.position.set(-6.0, -3.0, -4.0) |> ignore + scene.add(rimLight) + let bounceLight = createHemisphereLight("#3d4a56", "#141a1e", 0.9) + scene.add(bounceLight) let controls = createOrbitControls camera canvas setControlsTarget controls 0.0 0.0 0.0 diff --git a/src/SomhairlesDream.Frontend/Bindings.fs b/src/SomhairlesDream.Frontend/Bindings.fs index 19056a5..b6c4353 100644 --- a/src/SomhairlesDream.Frontend/Bindings.fs +++ b/src/SomhairlesDream.Frontend/Bindings.fs @@ -154,6 +154,33 @@ let createAmbientLight (color: string, intensity: float) : ThreeNode = jsNative [<Emit("new THREE.DirectionalLight($0, $1)")>] let createDirectionalLight (color: string, intensity: float) : ThreeNode = jsNative +[<Emit("new THREE.HemisphereLight($0, $1, $2)")>] +let createHemisphereLight (skyColor: string, groundColor: string, intensity: float) : ThreeNode = jsNative + +[<Emit("$0.toneMapping = THREE.ACESFilmicToneMapping")>] +let setToneMappingACES (renderer: obj) : unit = jsNative + +[<Emit("$0.toneMappingExposure = $1")>] +let setToneMappingExposure (renderer: obj, exposure: float) : unit = jsNative + +[<Emit("$0.outputColorSpace = THREE.SRGBColorSpace")>] +let setSRGBOutput (renderer: obj) : unit = jsNative + +[<Emit("new THREE.PMREMGenerator($0)")>] +let createPMREMGenerator (renderer: obj) : obj = jsNative + +[<Emit("new THREE.Scene()")>] +let createEnvScene () : obj = jsNative + +[<Emit("$0.fromScene($1, 0.04).texture")>] +let pmremFromScene (generator: obj, scene: obj) : obj = jsNative + +[<Emit("$0.environment = $1")>] +let setSceneEnvironment (scene: obj, texture: obj) : unit = jsNative + +[<Emit("$0.environmentIntensity = $1")>] +let setSceneEnvironmentIntensity (scene: obj, intensity: float) : unit = jsNative + [<Emit("new EventSource($0)")>] let createEventSource (url: string) : EventSource = jsNative |
