Files
morten-olsen.github.io/webpage/src/components/assets/background/background.tsx
Morten Olsen 3f5e941446 feat: init
2022-12-07 00:08:14 +01:00

135 lines
3.1 KiB
TypeScript

import React, { Suspense, useMemo, useRef } from 'react';
import { Canvas, useFrame, useLoader } from '@react-three/fiber';
import { Clock, Euler, Vector3 } from 'three';
import { TextureLoader } from 'three/src/loaders/TextureLoader';
import styled from 'styled-components';
const smoke = require('./smoke.png');
const Wrapper = styled.div`
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
`;
const FrameLimiter = () => {
const [clock] = React.useState(new Clock());
const [fps] = React.useState(10);
useFrame((state: any) => {
state.ready = false;
const timeUntilNextFrame = 1000 / fps - clock.getDelta();
setTimeout(() => {
state.ready = true;
state.invalidate();
}, Math.max(0, timeUntilNextFrame));
});
return <></>;
};
const Cloud = ({ texture }) => {
const ref = useRef<any>();
const width = window.innerWidth / 2;
const height = window.innerHeight / 2;
useFrame(() => {
if (!ref.current) {
return;
}
ref.current.rotation.z -= 0.003;
});
return (
<mesh
ref={ref}
rotation={new Euler(1.16, -0.12, Math.random() * Math.PI * 2)}
position={
new Vector3(
Math.random() * width - width / 2,
500,
Math.random() * height - height / 2
)
}
>
<planeBufferGeometry args={[500, 500]} />
<meshLambertMaterial
opacity={0.55}
args={[{ map: texture, transparent: true }]}
/>
</mesh>
);
};
const Clouds = () => {
const colorMap = useLoader(TextureLoader, smoke);
const items = useMemo(() => new Array(30).fill(undefined), []);
return (
<>
{items.map((_, i) => (
<Cloud key={i} texture={colorMap} />
))}
</>
);
};
const Scene = () => {
return (
<Canvas
onCreated={({ gl }) => {
gl.setClearColor('red');
}}
gl={{
antialias: false,
}}
camera={{
fov: 60,
aspect: 1,
near: 1,
far: 1000,
position: [0, 0, 1],
rotation: [1.16, -0.12, 0.27],
}}
>
<FrameLimiter />
<scene>
<perspectiveCamera
args={[60, window.innerWidth / window.innerHeight, 1, 1000]}
position={new Vector3(0, 0, 1)}
rotation={new Euler(1.16, -0.12, 0.27)}
/>
<ambientLight args={[0x555555]} />
<fogExp2 args={[0x03544e, 0.001]} />
<directionalLight args={[0xff8c19]} position={new Vector3(0, 0, 1)} />
<pointLight
args={[0xcc6600, 50, 450, 1.7]}
position={new Vector3(200, 300, 100)}
/>
<pointLight
args={[0xd8547e, 50, 450, 1.7]}
position={new Vector3(100, 300, 100)}
/>
<pointLight
args={[0x3677ac, 50, 450, 1.7]}
position={new Vector3(300, 300, 200)}
/>
<Suspense fallback={null}>
<Clouds />
</Suspense>
</scene>
</Canvas>
);
};
const Background = () => {
return (
<Wrapper suppressHydrationWarning={true}>
{typeof window !== 'undefined' && <Scene />}
</Wrapper>
);
};
export { Background };