feat(web): light 3D scene with image-based lighting

Replace the hand-placed light rig with an Environment built from Lightformers, giving MeshStandardMaterial objects consistent PBR lighting and richer color. Keep ContactShadows, which needs no light.
This commit is contained in:
2026-08-15 12:42:05 +08:00
parent 3dd3db5643
commit 7d9b5e49ad
+10 -8
View File
@@ -1,7 +1,7 @@
import { Suspense, useEffect, useRef, useState, type ReactNode } from 'react'; import { Suspense, useEffect, useRef, useState, type ReactNode } from 'react';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { Canvas } from '@react-three/fiber'; import { Canvas } from '@react-three/fiber';
import { Bounds, ContactShadows, OrbitControls, useProgress } from '@react-three/drei'; import { Bounds, ContactShadows, Environment, Lightformer, OrbitControls, useProgress } from '@react-three/drei';
import { BrightnessContrast, EffectComposer, ToneMapping, Vignette } from '@react-three/postprocessing'; import { BrightnessContrast, EffectComposer, ToneMapping, Vignette } from '@react-three/postprocessing';
import { ToneMappingMode } from 'postprocessing'; import { ToneMappingMode } from 'postprocessing';
@@ -73,7 +73,7 @@ export default function Scene({
<div <div
ref={containerRef} ref={containerRef}
className={`relative w-full overflow-hidden rounded-lg bg-linear-to-b from-zinc-300 to-zinc-400 ${ className={`relative w-full overflow-hidden rounded-lg bg-linear-to-b from-zinc-300 to-zinc-400 ${
fill ? 'h-full min-h-0' : 'aspect-[3/4]' fill ? 'h-full min-h-0' : 'aspect-3/4'
}`} }`}
> >
<LoadingOverlay /> <LoadingOverlay />
@@ -93,10 +93,12 @@ export default function Scene({
dpr={[1, 2]} dpr={[1, 2]}
gl={{ antialias: true, alpha: true }} gl={{ antialias: true, alpha: true }}
> >
<ambientLight intensity={0.5} /> <ambientLight intensity={0.1} />
<directionalLight position={[4, 6, 3]} intensity={1.4} />
<directionalLight position={[-4, 2, -3]} intensity={0.4} color="#b3c7ff" /> <Environment resolution={256}>
<pointLight position={[0, 3, 0]} intensity={0.3} /> <Lightformer intensity={2} position={[0, 5, 0]} scale={[10, 10, 1]} />
<Lightformer intensity={1} color="#b3c7ff" position={[-5, 2, -1]} scale={[3, 3, 1]} />
</Environment>
<Suspense fallback={null}> <Suspense fallback={null}>
<Bounds fit={fit} observe={fit} clip={fit}>{children}</Bounds> <Bounds fit={fit} observe={fit} clip={fit}>{children}</Bounds>
@@ -121,8 +123,8 @@ export default function Scene({
/> />
<EffectComposer> <EffectComposer>
<ToneMapping mode={ToneMappingMode.ACES_FILMIC} /> <ToneMapping mode={ToneMappingMode.AGX} />
<BrightnessContrast brightness={0.06} contrast={0} /> <BrightnessContrast brightness={0.25} contrast={.5} />
<Vignette eskil={false} offset={0.25} darkness={0.6} /> <Vignette eskil={false} offset={0.25} darkness={0.6} />
</EffectComposer> </EffectComposer>
</Canvas> </Canvas>