162 lines
4.3 KiB
TypeScript
162 lines
4.3 KiB
TypeScript
'use client';
|
|
|
|
import './page.css';
|
|
|
|
import { Environment, OrbitControls, useProgress } from "@react-three/drei";
|
|
import { Canvas } from '@react-three/fiber';
|
|
import { Bloom, BrightnessContrast, DepthOfField, EffectComposer, HueSaturation, Noise, SMAA, SSAO, Vignette } from '@react-three/postprocessing';
|
|
import { useLayoutEffect, useState } from "react";
|
|
import { folder, useControls, Leva } from 'leva';
|
|
import SealCube from './scene-components/sealcube';
|
|
import Terrain from './scene-components/terrain';
|
|
|
|
function Loader() {
|
|
const { progress, active } = useProgress();
|
|
const [visible, setVisible] = useState(true);
|
|
|
|
useLayoutEffect(() => {
|
|
if (!active && progress === 100) {
|
|
const timeout = setTimeout(() => setVisible(false), 500);
|
|
return () => clearTimeout(timeout);
|
|
}
|
|
}, [progress, active]);
|
|
|
|
return (
|
|
<div className={`loader ${!visible ? 'loader hidden' : ''}`}>
|
|
<picture>
|
|
<img src='niko/img/niko.jpg' className='niko-spin' />
|
|
</picture>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function Scene() {
|
|
const {
|
|
terrainDryColor,
|
|
terrainLushColor,
|
|
chunks,
|
|
chunkSize,
|
|
resolution,
|
|
hillScale,
|
|
hillHeight,
|
|
detailScale,
|
|
detailHeight,
|
|
grassDryColor,
|
|
grassLushColor,
|
|
grassCount,
|
|
grassSize,
|
|
grassLOD,
|
|
grassBlades,
|
|
grassSegments,
|
|
grassLODStart,
|
|
grassLODExponent
|
|
} = useControls('Environment', {
|
|
Terrain: folder({
|
|
terrainDryColor: '#20270a',
|
|
terrainLushColor: '#0f240f',
|
|
chunks: { value: 16, min: 4, max: 24, step: 2 },
|
|
chunkSize: { value: 10.0, min: 5.0, max: 40.0, step: 1.0 },
|
|
resolution: { value: 8.0, min: 4.0, max: 30.0, step: 1.0 },
|
|
hillScale: { value: 0.1, min: 0.01, max: 0.5, step: 0.01 },
|
|
hillHeight: { value: 6.0, min: 0.0, max: 20.0, step: 0.5 },
|
|
detailScale: { value: 1.0, min: 0.1, max: 5.0, step: 0.1 },
|
|
detailHeight: { value: 0.2, min: 0.0, max: 2.0, step: 0.05 },
|
|
}),
|
|
Grass: folder({
|
|
grassDryColor: '#495a17',
|
|
grassLushColor: '#255825',
|
|
grassCount: { value: 7000, min: 1000, max: 30000, step: 500 },
|
|
grassSize: { value: 0.6, min: 0.1, max: 2.0, step: 0.05 },
|
|
grassLOD: { value: 60, min: 10, max: 200, step: 5 },
|
|
grassBlades: { value: 3, min: 1, max: 4, step: 1 },
|
|
grassSegments: { value: 4, min: 1, max: 5, step: 1 },
|
|
grassLODStart: { value: 0.5, min: 0.0, max: 0.9, step: 0.05 },
|
|
grassLODExponent: { value: 1.0, min: 0.5, max: 3.0, step: 0.1 },
|
|
})
|
|
});
|
|
|
|
return (<>
|
|
<Environment
|
|
files={'niko/hdr/sky.hdr'}
|
|
environmentIntensity={1}
|
|
background
|
|
/>
|
|
|
|
<fogExp2 attach='fog' args={[0x9a9a9a, 0.01]} />
|
|
|
|
<Terrain
|
|
chunks={chunks}
|
|
chunkSize={chunkSize}
|
|
resolution={resolution}
|
|
scale={1}
|
|
hillScale={hillScale}
|
|
hillHeight={hillHeight}
|
|
detailScale={detailScale}
|
|
detailHeight={detailHeight}
|
|
grassCount={grassCount}
|
|
grassSize={grassSize}
|
|
grassLOD={grassLOD}
|
|
terrainDryColor={terrainDryColor}
|
|
terrainLushColor={terrainLushColor}
|
|
grassDryColor={grassDryColor}
|
|
grassLushColor={grassLushColor}
|
|
grassBlades={grassBlades}
|
|
grassSegments={grassSegments}
|
|
grassLODStart={grassLODStart}
|
|
grassLODExponent={grassLODExponent}
|
|
/>
|
|
|
|
<SealCube />
|
|
</>)
|
|
}
|
|
|
|
function PostProcessing() {
|
|
return (<EffectComposer>
|
|
<DepthOfField target={[0, 3, 0]} focalLength={10} bokehScale={5} />
|
|
<Vignette />
|
|
<Noise opacity={0.05} />
|
|
<Bloom
|
|
intensity={2}
|
|
luminanceThreshold={0.5}
|
|
luminanceSmoothing={0.1}
|
|
/>
|
|
<SMAA />
|
|
<HueSaturation saturation={0.1} />
|
|
<BrightnessContrast brightness={0.05} contrast={-0.1} />
|
|
</EffectComposer>)
|
|
}
|
|
|
|
export default function Seal() {
|
|
const isProduction = process.env.NODE_ENV === 'production';
|
|
|
|
return (
|
|
<>
|
|
<Leva hidden={isProduction} />
|
|
|
|
<Loader />
|
|
<Canvas
|
|
shadows
|
|
camera={{ position: [0, 5, 15], fov: 50, far: 100 }}
|
|
gl={{ antialias: true }}
|
|
className='canvas'
|
|
>
|
|
<Scene />
|
|
<PostProcessing />
|
|
|
|
<Environment
|
|
files={'niko/hdr/sky.hdr'}
|
|
environmentIntensity={1}
|
|
background
|
|
/>
|
|
|
|
<OrbitControls
|
|
target={[0, 3, 0]}
|
|
enablePan={false}
|
|
makeDefault
|
|
minDistance={2}
|
|
maxDistance={10}
|
|
/>
|
|
</Canvas>
|
|
</>
|
|
);
|
|
} |