style: format with prettier

This commit is contained in:
neru
2026-01-02 00:40:01 -03:00
parent 76209cfcd7
commit 8b1706b8fe
+153 -52
View File
@@ -4,7 +4,17 @@ import { OrbitControls, PerspectiveCamera } from '@react-three/drei';
import { Canvas, useLoader, useFrame } from '@react-three/fiber';
import { forwardRef, useLayoutEffect, useMemo, useRef } from 'react';
import { BufferAttribute, BufferGeometry, Mesh, Object3D, InstancedMesh, DoubleSide, TextureLoader, Color, MeshStandardMaterial } from 'three';
import {
BufferAttribute,
BufferGeometry,
Mesh,
Object3D,
InstancedMesh,
DoubleSide,
TextureLoader,
Color,
MeshStandardMaterial
} from 'three';
import './page.css';
import { createNoise2D } from 'simplex-noise';
@@ -12,7 +22,12 @@ import { useControls } from 'leva';
import grassVert from './shaders/grass.vert';
import grassFrag from './shaders/grass.frag';
import { Bloom, EffectComposer, Noise, Pixelation } from '@react-three/postprocessing';
import {
Bloom,
EffectComposer,
Noise,
Pixelation
} from '@react-three/postprocessing';
interface Shader {
uniforms: { [key: string]: { value: unknown } };
@@ -35,8 +50,10 @@ function getTerrainHeight(
const worldX = (worldXBase + localX) * 0.1;
const worldZ = (worldZBase + localZ) * 0.1;
const noiseHill = noise2D(worldX * hillScale, worldZ * hillScale) * hillHeight;
const noiseDetail = noise2D(worldX * detailScale, worldZ * detailScale) * detailHeight;
const noiseHill =
noise2D(worldX * hillScale, worldZ * hillScale) * hillHeight;
const noiseDetail =
noise2D(worldX * detailScale, worldZ * detailScale) * detailHeight;
return (noiseHill + noiseDetail) * scale;
}
@@ -56,17 +73,39 @@ interface GrassProps {
enableShadows?: boolean;
}
function Grass({ x, y, size, count, grassSize, scale, hillScale, hillHeight, detailScale, detailHeight, noise2D }: GrassProps) {
function Grass({
x,
y,
size,
count,
grassSize,
scale,
hillScale,
hillHeight,
detailScale,
detailHeight,
noise2D
}: GrassProps) {
const meshRef = useRef<InstancedMesh>(null);
const dummyRef = useRef<Object3D>(new Object3D());
const [alphaMap, normalMap] = useLoader(TextureLoader, ['/img/grass_alpha.png', '/img/grass_normal.png']);
const [alphaMap, normalMap] = useLoader(TextureLoader, [
'/img/grass_alpha.png',
'/img/grass_normal.png'
]);
const materialRef = useRef<MeshStandardMaterial & { userData: { shader: Shader } }>(null);
const materialRef = useRef<
MeshStandardMaterial & { userData: { shader: Shader } }
>(null);
useFrame((state) => {
if (materialRef.current && materialRef.current.userData && materialRef.current.userData.shader) {
(materialRef.current.userData.shader as Shader).uniforms.uTime.value = state.clock.getElapsedTime();
if (
materialRef.current &&
materialRef.current.userData &&
materialRef.current.userData.shader
) {
(materialRef.current.userData.shader as Shader).uniforms.uTime.value =
state.clock.getElapsedTime();
}
});
@@ -77,21 +116,40 @@ function Grass({ x, y, size, count, grassSize, scale, hillScale, hillHeight, det
const h = 2;
const positions = [
-w, 0, 0, w, 0, 0, -w, h, 0, w, h, 0,
0, 0, w, 0, 0, -w, 0, h, w, 0, h, -w
-w,
0,
0,
w,
0,
0,
-w,
h,
0,
w,
h,
0,
0,
0,
w,
0,
0,
-w,
0,
h,
w,
0,
h,
-w
];
const uvs = [
0, 0, 1, 0, 0, 1, 1, 1,
0, 0, 1, 0, 0, 1, 1, 1
];
const uvs = [0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1];
const indices = [
0, 1, 2, 2, 1, 3,
4, 5, 6, 6, 5, 7
];
const indices = [0, 1, 2, 2, 1, 3, 4, 5, 6, 6, 5, 7];
geo.setAttribute('position', new BufferAttribute(new Float32Array(positions), 3));
geo.setAttribute(
'position',
new BufferAttribute(new Float32Array(positions), 3)
);
geo.setAttribute('uv', new BufferAttribute(new Float32Array(uvs), 2));
geo.setIndex(indices);
geo.computeVertexNormals();
@@ -133,7 +191,7 @@ function Grass({ x, y, size, count, grassSize, scale, hillScale, hillHeight, det
dummy.rotation.x = (Math.random() - 0.5) * 0.2;
dummy.rotation.z = (Math.random() - 0.5) * 0.2;
const baseScale = grassSize + (Math.random() * grassSize * 0.5);
const baseScale = grassSize + Math.random() * grassSize * 0.5;
const heightMult = 0.5 + Math.random() * 1.0;
dummy.scale.set(baseScale, baseScale * heightMult, baseScale);
@@ -154,10 +212,24 @@ function Grass({ x, y, size, count, grassSize, scale, hillScale, hillHeight, det
meshRef.current.setColorAt(i, color);
}
meshRef.current.instanceMatrix.needsUpdate = true;
if (meshRef.current.instanceColor) meshRef.current.instanceColor.needsUpdate = true;
}, [x, y, size, count, grassSize, scale, hillScale, hillHeight, detailScale, detailHeight, noise2D]);
if (meshRef.current.instanceColor)
meshRef.current.instanceColor.needsUpdate = true;
}, [
x,
y,
size,
count,
grassSize,
scale,
hillScale,
hillHeight,
detailScale,
detailHeight,
noise2D
]);
const onBeforeCompile = useMemo(() => (shader: Shader) => {
const onBeforeCompile = useMemo(
() => (shader: Shader) => {
shader.uniforms.uTime = { value: 0 };
shader.vertexShader = `
@@ -222,7 +294,9 @@ function Grass({ x, y, size, count, grassSize, scale, hillScale, hillHeight, det
if (materialRef.current) {
materialRef.current.userData.shader = shader;
}
}, []);
},
[]
);
return (
<instancedMesh
@@ -233,7 +307,7 @@ function Grass({ x, y, size, count, grassSize, scale, hillScale, hillHeight, det
>
<meshStandardMaterial
ref={materialRef}
color="#ffffff"
color='#ffffff'
side={DoubleSide}
alphaMap={alphaMap}
alphaTest={0.5}
@@ -247,22 +321,37 @@ function Grass({ x, y, size, count, grassSize, scale, hillScale, hillHeight, det
}
interface TerrainChunkProps {
x: number,
y: number,
size: number,
resolution: number,
scale: number,
hillScale: number,
hillHeight: number,
detailScale: number,
detailHeight: number,
x: number;
y: number;
size: number;
resolution: number;
scale: number;
hillScale: number;
hillHeight: number;
detailScale: number;
detailHeight: number;
noise2D: (x: number, y: number) => number;
wireframe?: boolean;
grassCount: number;
grassSize: number;
grassLOD: number;
}
function TerrainChunk({ x, y, size, resolution, scale, hillScale, hillHeight, detailScale, detailHeight, noise2D, wireframe = false, grassCount, grassSize, grassLOD }: TerrainChunkProps) {
function TerrainChunk({
x,
y,
size,
resolution,
scale,
hillScale,
hillHeight,
detailScale,
detailHeight,
noise2D,
wireframe = false,
grassCount,
grassSize,
grassLOD
}: TerrainChunkProps) {
const distance = Math.sqrt((x * size) ** 2 + (y * size) ** 2);
let adjustedGrassCount = grassCount;
@@ -271,7 +360,7 @@ function TerrainChunk({ x, y, size, resolution, scale, hillScale, hillHeight, de
} else if (distance > grassLOD * 0.6) {
const fadeStart = grassLOD * 0.6;
const fadeRange = grassLOD * 0.4;
const fadeFactor = 1.0 - ((distance - fadeStart) / fadeRange);
const fadeFactor = 1.0 - (distance - fadeStart) / fadeRange;
adjustedGrassCount = Math.floor(grassCount * fadeFactor * fadeFactor);
}
const meshRef = useRef<Mesh>(null);
@@ -326,7 +415,10 @@ function TerrainChunk({ x, y, size, resolution, scale, hillScale, hillHeight, de
indices.push(topRight, bottomLeft, bottomRight);
}
}
geo.setAttribute('position', new BufferAttribute(new Float32Array(vertices), 3));
geo.setAttribute(
'position',
new BufferAttribute(new Float32Array(vertices), 3)
);
const colors: Array<number> = [];
for (let iz = 0; iz < resolution; iz++) {
@@ -354,7 +446,18 @@ function TerrainChunk({ x, y, size, resolution, scale, hillScale, hillHeight, de
geo.computeVertexNormals();
return geo;
}, [x, y, size, resolution, scale, hillScale, hillHeight, detailScale, detailHeight, noise2D]);
}, [
x,
y,
size,
resolution,
scale,
hillScale,
hillHeight,
detailScale,
detailHeight,
noise2D
]);
return (
<group>
@@ -388,7 +491,7 @@ function TerrainChunk({ x, y, size, resolution, scale, hillScale, hillHeight, de
/>
)}
</group>
)
);
}
interface TerrainProps {
@@ -396,10 +499,10 @@ interface TerrainProps {
chunkSize?: number;
resolution?: number;
scale?: number;
hillScale: number,
hillHeight: number,
detailScale: number,
detailHeight: number,
hillScale: number;
hillHeight: number;
detailScale: number;
detailHeight: number;
wireframe?: boolean;
grassCount?: number;
grassSize?: number;
@@ -425,8 +528,7 @@ function Terrain({
const chunkPositions = useMemo(() => {
const positions: [number, number][] = [];
for (let x = 0; x < chunks; x++)
for (let y = 0; y < chunks; y++)
positions.push([x + offset, y + offset]);
for (let y = 0; y < chunks; y++) positions.push([x + offset, y + offset]);
return positions;
}, [chunks, offset]);
@@ -502,17 +604,16 @@ export default function Home() {
>
<EffectComposer>
<Noise opacity={0.1} />
<Bloom intensity={2}
<Bloom
intensity={2}
luminanceThreshold={0.5}
luminanceSmoothing={0.1} />
luminanceSmoothing={0.1}
/>
<Pixelation />
</EffectComposer>
<ambientLight intensity={0.5} />
<directionalLight
position={[10, 20, 5]}
intensity={1}
/>
<directionalLight position={[10, 20, 5]} intensity={1} />
<Terrain
chunks={8.0}
chunkSize={10.0}