feat: postprocessing + shadows

This commit is contained in:
Florian Sylvain
2024-03-14 02:24:16 +01:00
parent 461044969e
commit 8404527eb1
5 changed files with 106 additions and 44 deletions
+1
View File
@@ -12,6 +12,7 @@
"dependencies": { "dependencies": {
"@react-three/drei": "^9.99.7", "@react-three/drei": "^9.99.7",
"@react-three/fiber": "^8.15.19", "@react-three/fiber": "^8.15.19",
"@react-three/postprocessing": "^2.16.2",
"@types/three": "^0.162.0", "@types/three": "^0.162.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
+51
View File
@@ -11,6 +11,9 @@ dependencies:
'@react-three/fiber': '@react-three/fiber':
specifier: ^8.15.19 specifier: ^8.15.19
version: 8.15.19(react-dom@18.2.0)(react@18.2.0)(three@0.162.0) version: 8.15.19(react-dom@18.2.0)(react@18.2.0)(three@0.162.0)
'@react-three/postprocessing':
specifier: ^2.16.2
version: 2.16.2(@react-three/fiber@8.15.19)(@types/three@0.162.0)(react@18.2.0)(three@0.162.0)
'@types/three': '@types/three':
specifier: ^0.162.0 specifier: ^0.162.0
version: 0.162.0 version: 0.162.0
@@ -752,6 +755,25 @@ packages:
zustand: 3.7.2(react@18.2.0) zustand: 3.7.2(react@18.2.0)
dev: false dev: false
/@react-three/postprocessing@2.16.2(@react-three/fiber@8.15.19)(@types/three@0.162.0)(react@18.2.0)(three@0.162.0):
resolution: {integrity: sha512-2ya1gXLDpzyfbELobi3rPHNNZZCrCfyq20GMYJD1yD7ZyBFSpRG9YSPMBnOal6A89kXanPBw273h6/Dqev0n7g==}
peerDependencies:
'@react-three/fiber': '>=8.0'
react: '>=18.0'
three: '>= 0.138.0'
dependencies:
'@react-three/fiber': 8.15.19(react-dom@18.2.0)(react@18.2.0)(three@0.162.0)
buffer: 6.0.3
maath: 0.6.0(@types/three@0.162.0)(three@0.162.0)
n8ao: 1.8.1(postprocessing@6.35.2)(three@0.162.0)
postprocessing: 6.35.2(three@0.162.0)
react: 18.2.0
three: 0.162.0
three-stdlib: 2.29.5(three@0.162.0)
transitivePeerDependencies:
- '@types/three'
dev: false
/@rollup/rollup-android-arm-eabi@4.12.1: /@rollup/rollup-android-arm-eabi@4.12.1:
resolution: {integrity: sha512-iU2Sya8hNn1LhsYyf0N+L4Gf9Qc+9eBTJJJsaOGUp+7x4n2M9dxTt8UvhJl3oeftSjblSlpCfvjA/IfP3g5VjQ==} resolution: {integrity: sha512-iU2Sya8hNn1LhsYyf0N+L4Gf9Qc+9eBTJJJsaOGUp+7x4n2M9dxTt8UvhJl3oeftSjblSlpCfvjA/IfP3g5VjQ==}
cpu: [arm] cpu: [arm]
@@ -1820,6 +1842,16 @@ packages:
three: 0.162.0 three: 0.162.0
dev: false dev: false
/maath@0.6.0(@types/three@0.162.0)(three@0.162.0):
resolution: {integrity: sha512-dSb2xQuP7vDnaYqfoKzlApeRcR2xtN8/f7WV/TMAkBC8552TwTLtOO0JTcSygkYMjNDPoo6V01jTw/aPi4JrMw==}
peerDependencies:
'@types/three': '>=0.144.0'
three: '>=0.144.0'
dependencies:
'@types/three': 0.162.0
three: 0.162.0
dev: false
/merge2@1.4.1: /merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@@ -1862,6 +1894,16 @@ packages:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true dev: true
/n8ao@1.8.1(postprocessing@6.35.2)(three@0.162.0):
resolution: {integrity: sha512-biKUW09KnflZpeWmbCy1gjuiyZsbeG6y+EsqV+1IDqQ1KqEydXc6nUUseZp9ZRbjvEOPnsvsjaTce8Pta0803A==}
peerDependencies:
postprocessing: '>=6.30.0'
three: '>=0.137'
dependencies:
postprocessing: 6.35.2(three@0.162.0)
three: 0.162.0
dev: false
/nanoid@3.3.7: /nanoid@3.3.7:
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -1957,6 +1999,15 @@ packages:
source-map-js: 1.0.2 source-map-js: 1.0.2
dev: true dev: true
/postprocessing@6.35.2(three@0.162.0):
resolution: {integrity: sha512-yGmidrVzA1dSEmExYGgWOGcRvyOVahvurNo9iuzOonRCY6f1hnJe6/HMVSnKV9ppjLtCTqzZOI9iz8CACkmijw==}
engines: {node: '>= 0.13.2'}
peerDependencies:
three: '>= 0.152.0 < 0.163.0'
dependencies:
three: 0.162.0
dev: false
/potpack@1.0.2: /potpack@1.0.2:
resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==}
dev: false dev: false
+35 -32
View File
@@ -1,16 +1,12 @@
import "./App.css"; import "./App.css";
import { Canvas } from "@react-three/fiber"; import { Canvas } from "@react-three/fiber";
import { import { KeyboardControls } from "@react-three/drei";
KeyboardControls,
Sparkles,
Text,
TransformControls,
} from "@react-three/drei";
import { MutableRefObject, useEffect, useRef, useState } from "react"; import { MutableRefObject, useEffect, useRef, useState } from "react";
import { Vector3 } from "three"; import { Vector3 } from "three";
import { Cubes } from "./components/Cubes"; import { Cubes } from "./components/Cubes";
import { Player } from "./components/Player"; import { Player } from "./components/Player";
import { Bloom, EffectComposer, Vignette } from "@react-three/postprocessing";
function App() { function App() {
const CUBES_QT = 20; const CUBES_QT = 20;
@@ -35,35 +31,21 @@ function App() {
className="container" className="container"
onClick={() => container.current?.requestPointerLock()} onClick={() => container.current?.requestPointerLock()}
> >
<Canvas className="canvas" ref={container}> <Canvas className="canvas" ref={container} shadows>
<Cubes cubesPosition={cubes}></Cubes> <Cubes cubesPosition={cubes}></Cubes>
<TransformControls position={[20, 10, 0]}>
<Text <mesh
color={"green"} rotation={[-Math.PI / 2, 0, 0]}
fontSize={8} position={[0, 0, 0]}
anchorX={"center"} receiveShadow
anchorY={"middle"} >
>
Bonsoir
</Text>
</TransformControls>
<group>
<Sparkles
color={"blue"}
count={100}
size={20}
scale={[20, 10, 20]}
speed={25}
position={[20, 0, 20]}
></Sparkles>
</group>
<mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, 0, 0]}>
<planeGeometry attach={"geometry"} args={[100, 100]}></planeGeometry> <planeGeometry attach={"geometry"} args={[100, 100]}></planeGeometry>
<meshStandardMaterial <meshStandardMaterial
attach={"material"} attach={"material"}
color={"lightblue"} color={"green"}
></meshStandardMaterial> ></meshStandardMaterial>
</mesh> </mesh>
<KeyboardControls <KeyboardControls
map={[ map={[
{ keys: ["w", "ArrowUp"], name: "moveForward" }, { keys: ["w", "ArrowUp"], name: "moveForward" },
@@ -80,11 +62,32 @@ function App() {
} }
></Player> ></Player>
</KeyboardControls> </KeyboardControls>
<ambientLight intensity={Math.PI / 2} /> <ambientLight intensity={Math.PI / 2} />
<directionalLight <directionalLight
intensity={Math.PI / 2} castShadow
position={[2, 2, 2]} position={[100, 100, 100]}
></directionalLight> shadow-mapSize={[4096, 4096]}
intensity={5}
>
<orthographicCamera
attach="shadow-camera"
args={[-50, 50, 50, -50]}
/>
</directionalLight>
<color args={["lightblue"]} attach={"background"}></color>
<fog attach={"fog"} args={["lightblue", 0, 100]}></fog>
<gridHelper args={[100, 100]}></gridHelper>
<axesHelper args={[100]}></axesHelper>
<EffectComposer>
<Bloom
luminanceThreshold={0.2}
luminanceSmoothing={0.8}
height={300}
/>
<Vignette eskil={false} offset={0.2} darkness={0.8} />
</EffectComposer>
</Canvas> </Canvas>
</main> </main>
); );
+7 -2
View File
@@ -5,7 +5,7 @@ import { useFrame } from "@react-three/fiber";
export function Cubes(props: { cubesPosition: Vector3[] }) { export function Cubes(props: { cubesPosition: Vector3[] }) {
const CUBE_SPEED = 10; const CUBE_SPEED = 10;
const CUBE_AMPLITUDE = 2; const CUBE_AMPLITUDE = 2;
const CUBE_HEIGHT = 2; const CUBE_HEIGHT = 4;
const [cubes, setCubes] = useState<Vector3[]>( const [cubes, setCubes] = useState<Vector3[]>(
Array.from(props.cubesPosition) Array.from(props.cubesPosition)
@@ -30,7 +30,12 @@ export function Cubes(props: { cubesPosition: Vector3[] }) {
return cubes.map((cube) => { return cubes.map((cube) => {
if (!cube) return; if (!cube) return;
return ( return (
<mesh position={cube} key={`${cube.x}-${cube.z}`}> <mesh
position={cube}
key={`${cube.x}-${cube.z}`}
castShadow
receiveShadow
>
<boxGeometry attach={"geometry"}></boxGeometry> <boxGeometry attach={"geometry"}></boxGeometry>
<meshStandardMaterial <meshStandardMaterial
attach={"material"} attach={"material"}
+12 -10
View File
@@ -1,7 +1,7 @@
import { useAnimations, useGLTF, useKeyboardControls } from "@react-three/drei"; import { useAnimations, useGLTF, useKeyboardControls } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber"; import { useFrame, useThree } from "@react-three/fiber";
import { MutableRefObject, useCallback, useEffect, useState } from "react"; import { MutableRefObject, useCallback, useEffect, useState } from "react";
import { Euler, Quaternion, Vector2, Vector3 } from "three"; import { Euler, Mesh, Quaternion, Vector2, Vector3 } from "three";
import { degToRad } from "three/src/math/MathUtils.js"; import { degToRad } from "three/src/math/MathUtils.js";
export interface KeyPressed { export interface KeyPressed {
@@ -13,13 +13,15 @@ export interface KeyPressed {
sprint: boolean; sprint: boolean;
} }
const PLAYER_SPEED = 4.75; // TODO NERF
export function Player(props: { export function Player(props: {
container: MutableRefObject<HTMLCanvasElement>; container: MutableRefObject<HTMLCanvasElement>;
}): JSX.Element { }): JSX.Element {
const model = useGLTF("/Adventurer.glb"); const model = useGLTF("/Adventurer.glb");
const animations = useAnimations(model.animations, model.scene); const animations = useAnimations(model.animations, model.scene);
// const walk = animations.actions["CharacterArmature|Walk"]; // const walk = animations.actions["CharacterArmature|Walk"];
const run = animations.actions["CharacterArmature|Run"]; const run = animations.actions["CharacterArmature|Run"];
const idle = animations.actions["CharacterArmature|Idle"]; const idle = animations.actions["CharacterArmature|Idle"];
@@ -30,6 +32,7 @@ export function Player(props: {
const [pivotY, setPivotY] = useState(0); const [pivotY, setPivotY] = useState(0);
const [player, setPlayer] = useState<Vector3>(new Vector3(0, 0, 0)); const [player, setPlayer] = useState<Vector3>(new Vector3(0, 0, 0));
const [mouseRef, setMouseRef] = useState(new Vector2()); const [mouseRef, setMouseRef] = useState(new Vector2());
const camera = useThree((state) => state.camera); const camera = useThree((state) => state.camera);
const radius = 2; const radius = 2;
@@ -37,20 +40,21 @@ export function Player(props: {
useEffect(() => { useEffect(() => {
idle?.play(); idle?.play();
model.scene.traverse((child) => {
if (child instanceof Mesh) child.castShadow = true;
});
}); });
useFrame((_, delta) => { useFrame((_, delta) => {
const speed = 8;
const move = new Vector3(); const move = new Vector3();
// TODO Replace getKeys with the subscription system // TODO Replace getKeys with the subscription system
// const keyPressed = getKeys() as unknown as KeyPressed;
if (getKeys().moveForward) move.z += 1; if (getKeys().moveForward) move.z += 1;
if (getKeys().moveBackward) move.z -= 1; if (getKeys().moveBackward) move.z -= 1;
if (getKeys().moveLeft) move.x += 1; if (getKeys().moveLeft) move.x += 1;
if (getKeys().moveRight) move.x -= 1; if (getKeys().moveRight) move.x -= 1;
move.applyEuler(new Euler(0, pivotX - degToRad(180), 0)); move.applyEuler(new Euler(0, pivotX - degToRad(180), 0));
move.multiplyScalar(speed * delta); move.multiplyScalar(PLAYER_SPEED * delta);
camera.position.x = radius * Math.sin(pivotX) * Math.cos(pivotY) + player.x; camera.position.x = radius * Math.sin(pivotX) * Math.cos(pivotY) + player.x;
camera.position.y = radius * Math.sin(pivotY) + player.y + yOffset; camera.position.y = radius * Math.sin(pivotY) + player.y + yOffset;
@@ -66,11 +70,7 @@ export function Player(props: {
if (Object.values(getKeys()).some((key) => key)) { if (Object.values(getKeys()).some((key) => key)) {
setPlayer(player.clone().add(move)); setPlayer(player.clone().add(move));
setIsWalking(true); setIsWalking(true);
} else {
setIsWalking(false);
}
if (isWalking) {
const targetRotation = new Quaternion(); const targetRotation = new Quaternion();
targetRotation.setFromEuler( targetRotation.setFromEuler(
new Euler( new Euler(
@@ -89,7 +89,9 @@ export function Player(props: {
new Quaternion().setFromEuler(new Euler(0, -cameraRotation.y, 0)) new Quaternion().setFromEuler(new Euler(0, -cameraRotation.y, 0))
); );
model.scene.quaternion.slerp(targetRotation, 0.05); model.scene.quaternion.slerp(targetRotation, 0.2);
} else {
setIsWalking(false);
} }
}); });