starfield intro anim, still need to make a smooth transition.

This commit is contained in:
ad044 2020-09-09 23:35:13 +04:00
parent 1fae1488b7
commit 85a0461572

View file

@ -10,9 +10,30 @@ type StarRefsAndIncrementors = [
type StarfieldProps = {
starfieldPosY: Interpolation<number, number>;
introStarfieldVisible: boolean;
};
type StarfieldObjectData = {
starPoses: number[][];
ref: React.MutableRefObject<React.RefObject<THREE.Object3D>[]>;
rotation: number[];
positionSpecifier: number[];
uniform?:
| { color1: { value: THREE.Color }; color2: { value: THREE.Color } }
| undefined;
};
type IntroStarfieldObjectData = {
starPoses: number[][];
ref: React.MutableRefObject<React.RefObject<THREE.Object3D>[]>;
uniform?:
| { color1: { value: THREE.Color }; color2: { value: THREE.Color } }
| undefined;
};
const Starfield = memo((props: StarfieldProps) => {
const introStarfieldGroupRef = useRef<THREE.Object3D>();
const uniformConstructor = (col: string) => {
return {
color1: {
@ -24,12 +45,6 @@ const Starfield = memo((props: StarfieldProps) => {
};
};
const [blueUniforms, cyanUniforms, whiteUniforms] = [
"blue",
"cyan",
"gray",
].map((color: string) => useMemo(() => uniformConstructor(color), [color]));
const vertexShader = `
varying vec2 vUv;
@ -58,13 +73,19 @@ const Starfield = memo((props: StarfieldProps) => {
const lcgInstance = LCG(1664525, 1013904223, 2 ** 32, 2);
const [blueUniforms, cyanUniforms, whiteUniforms] = [
"blue",
"cyan",
"gray",
].map((color: string) => useMemo(() => uniformConstructor(color), [color]));
const [
posesBlueFromRight,
posesBlueFromLeft,
posesCyanFromRight,
posesCyanFromLeft,
posesWhiteFromLeft,
] = [40, 40, 10, 5, 5].map((x) =>
] = [30, 30, 20, 20, 5].map((x) =>
Array.from({ length: x }, () => [
lcgInstance() / 1000000000,
lcgInstance() / 1000000000,
@ -90,6 +111,28 @@ const Starfield = memo((props: StarfieldProps) => {
)
);
const [introPosesBlue, introPosesCyan, introPosesWhite] = [
80,
80,
60,
].map((x) =>
Array.from({ length: x }, () => [
lcgInstance() / 1000000050,
lcgInstance() / 100000099,
lcgInstance() / 1000000050,
])
);
const [introBlueRef, introCyanRef, introWhiteRef] = [
introPosesBlue,
introPosesCyan,
introPosesWhite,
].map((poses) =>
useRef<RefObject<THREE.Object3D>[]>(
poses.map(() => createRef<THREE.Object3D>())
)
);
// these arrays contain refs to the 3d planes and the increment values that they should move with across
// the screen
const fromRightStarRefsAndIncrementors: StarRefsAndIncrementors = [
@ -104,154 +147,148 @@ const Starfield = memo((props: StarfieldProps) => {
];
useFrame(() => {
// planes (stars) coming from right move to positive X and negative Z direction
fromRightStarRefsAndIncrementors.forEach((el) => {
el[0].current.forEach((posRef: RefObject<THREE.Object3D>) => {
if (posRef.current!.position.x < -1) {
posRef.current!.position.x += el[1];
posRef.current!.position.z -= el[1];
} else {
posRef.current!.position.x -= 0.03;
posRef.current!.position.z += 0.03;
}
if (props.introStarfieldVisible) {
introStarfieldGroupRef.current!.position.y += 0.2;
} else {
// planes (stars) coming from right move to positive X and negative Z direction
fromRightStarRefsAndIncrementors.forEach((el) => {
el[0].current.forEach((posRef: RefObject<THREE.Object3D>) => {
if (posRef.current!.position.x < -1) {
posRef.current!.position.x += el[1];
posRef.current!.position.z -= el[1];
} else {
posRef.current!.position.x -= 0.03;
posRef.current!.position.z += 0.03;
}
});
});
});
// the ones that are coming from left move to negative X and Z
fromLeftStarRefsAndIncrementors.forEach((el) => {
el[0].current.forEach((posRef: RefObject<THREE.Object3D>) => {
if (posRef.current!.position.x > 3) {
posRef.current!.position.x -= el[1];
posRef.current!.position.z -= el[1];
} else {
posRef.current!.position.x += 0.03;
posRef.current!.position.z += 0.03;
}
// the ones that are coming from left move to negative X and Z
fromLeftStarRefsAndIncrementors.forEach((el) => {
el[0].current.forEach((posRef: RefObject<THREE.Object3D>) => {
if (posRef.current!.position.x > 3) {
posRef.current!.position.x -= el[1];
posRef.current!.position.z -= el[1];
} else {
posRef.current!.position.x += 0.03;
posRef.current!.position.z += 0.03;
}
});
});
});
}
});
return (
const mainStarfieldObjects = [
{
starPoses: posesBlueFromRight,
ref: blueFromRightRef,
rotation: [1.7, 0, 0.9],
positionSpecifier: [0, 0, 0],
uniform: blueUniforms,
},
{
starPoses: posesBlueFromLeft,
ref: blueFromLeftRef,
rotation: [1.7, 0, -0.9],
positionSpecifier: [-2.4, -0.5, 2],
uniform: blueUniforms,
},
{
starPoses: posesCyanFromRight,
ref: cyanFromRightRef,
rotation: [1.7, 0, 0.9],
positionSpecifier: [-1.3, 0, 1.5],
uniform: cyanUniforms,
},
{
starPoses: posesCyanFromLeft,
ref: cyanFromLeftRef,
rotation: [1.7, 0, -0.9],
positionSpecifier: [-1.3, 0, 2.5],
uniform: cyanUniforms,
},
{
starPoses: posesWhiteFromLeft,
ref: whiteFromLeftRef,
rotation: [1.7, 0, -0.9],
positionSpecifier: [-1.3, 0.5, 1.5],
uniform: whiteUniforms,
},
];
const introStarfieldObjects = [
{ starPoses: introPosesBlue, ref: introBlueRef, uniform: blueUniforms },
{ starPoses: introPosesCyan, ref: introCyanRef, uniform: cyanUniforms },
{ starPoses: introPosesWhite, ref: introWhiteRef, uniform: whiteUniforms },
];
return props.introStarfieldVisible ? (
<a.group
position={[-0.7, 0, -4]}
ref={introStarfieldGroupRef}
position={[-2, -20, -2]}
rotation={[0, 0, 0]}
visible={props.introStarfieldVisible}
>
{introStarfieldObjects.map((obj: IntroStarfieldObjectData) =>
obj.starPoses.map((pos: number[], idx: number) => {
return (
<mesh
ref={obj.ref.current[idx]}
scale={[0.01, 2, -0.5]}
position={[pos[0], pos[1], pos[2]]}
key={pos[0]}
renderOrder={-1}
>
<planeGeometry attach="geometry" />
<shaderMaterial
attach="material"
uniforms={obj.uniform}
fragmentShader={fragmentShader}
vertexShader={vertexShader}
side={THREE.DoubleSide}
transparent={true}
depthWrite={false}
/>
</mesh>
);
})
)}
</a.group>
) : (
<a.group
position={[-0.7, 0, -5]}
rotation={[0, 0, 0]}
position-y={props.starfieldPosY}
>
{posesBlueFromRight.map((pos: number[], idx: number) => {
return (
<mesh
ref={blueFromRightRef.current[idx]}
scale={[0.01, 2, 1]}
rotation={[1.7, 0, 0.9]}
position={[pos[0], pos[1], pos[2]]}
key={pos[0]}
renderOrder={-1}
>
<planeGeometry attach="geometry" />
<shaderMaterial
attach="material"
uniforms={blueUniforms}
fragmentShader={fragmentShader}
vertexShader={vertexShader}
side={THREE.DoubleSide}
transparent={true}
depthWrite={false}
/>
</mesh>
);
})}
{posesBlueFromLeft.map((pos: number[], idx: number) => {
return (
<mesh
ref={blueFromLeftRef.current[idx]}
scale={[0.01, 2, 1]}
rotation={[1.7, 0, -0.9]}
position={[pos[0] - 2.4, pos[1] - 0.5, pos[2]]}
key={pos[0]}
renderOrder={-1}
>
<planeGeometry attach="geometry" />
<shaderMaterial
attach="material"
uniforms={blueUniforms}
fragmentShader={fragmentShader}
vertexShader={vertexShader}
side={THREE.DoubleSide}
transparent={true}
depthWrite={false}
/>
</mesh>
);
})}
{posesCyanFromRight.map((pos: number[], idx: number) => {
return (
<mesh
ref={cyanFromRightRef.current[idx]}
scale={[0.01, 0.9, 1]}
position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]}
rotation={[1.7, 0, 0.9]}
renderOrder={-1}
key={pos[0]}
>
<planeGeometry attach="geometry" />
<shaderMaterial
attach="material"
uniforms={cyanUniforms}
fragmentShader={fragmentShader}
vertexShader={vertexShader}
side={THREE.DoubleSide}
transparent={true}
depthWrite={false}
/>
</mesh>
);
})}
{posesCyanFromLeft.map((pos: number[], idx: number) => {
return (
<mesh
ref={cyanFromLeftRef.current[idx]}
scale={[0.01, 0.9, 1]}
position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]}
rotation={[1.7, 0, -0.9]}
renderOrder={-1}
key={pos[0]}
>
<planeGeometry attach="geometry" />
<shaderMaterial
attach="material"
uniforms={cyanUniforms}
fragmentShader={fragmentShader}
vertexShader={vertexShader}
side={THREE.DoubleSide}
transparent={true}
depthWrite={false}
/>
</mesh>
);
})}
{posesWhiteFromLeft.map((pos: number[], idx: number) => {
return (
<mesh
ref={whiteFromLeftRef.current[idx]}
scale={[0.01, 0.9, 1]}
position={[pos[0] - 1.3, pos[1] + 0.5, pos[2] + 1.5]}
rotation={[1.7, 0, -0.9]}
renderOrder={-1}
key={pos[0]}
>
<planeGeometry attach="geometry" />
<shaderMaterial
attach="material"
uniforms={whiteUniforms}
fragmentShader={fragmentShader}
vertexShader={vertexShader}
side={THREE.DoubleSide}
transparent={true}
depthWrite={false}
/>
</mesh>
);
})}
{mainStarfieldObjects.map((obj: StarfieldObjectData) =>
obj.starPoses.map((pos: number[], idx: number) => {
return (
<mesh
ref={obj.ref.current[idx]}
position={[
pos[0] + obj.positionSpecifier[0],
pos[1] + obj.positionSpecifier[1],
pos[2] + obj.positionSpecifier[2],
]}
rotation={obj.rotation as [number, number, number]}
scale={[0.01, 2, -0.5]}
renderOrder={-1}
key={pos[0]}
>
<planeGeometry attach="geometry" />
<shaderMaterial
attach="material"
uniforms={obj.uniform}
fragmentShader={fragmentShader}
vertexShader={vertexShader}
side={THREE.DoubleSide}
transparent={true}
depthWrite={false}
/>
</mesh>
);
})
)}
</a.group>
);
});