working on procedurally generated gray ring, still wip.

This commit is contained in:
ad044 2020-09-18 20:49:11 +04:00
parent acc36a826e
commit 5f473325fc
8 changed files with 165 additions and 76 deletions

Binary file not shown.

View file

@ -1,42 +1,142 @@
import { draco } from "drei"; import React, { memo, useMemo } from "react";
import React, { memo } from "react";
import { useLoader } from "react-three-fiber";
import * as THREE from "three"; import * as THREE from "three";
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; import lofTexture from "../static/sprites/lof.png";
import holeTexture from "../static/sprites/hole.png";
import lifeTexture from "../static/sprites/life.png";
import { useLoader } from "react-three-fiber";
type GrayRingProps = { type GrayRingProps = {
grayRingPosY: number; grayRingPosY: number;
}; };
type GLTFResult = GLTF & {
nodes: {
LainRing: THREE.Mesh;
};
materials: {
RingTexture: THREE.MeshStandardMaterial;
};
};
const GrayRing = memo((props: GrayRingProps) => { const GrayRing = memo((props: GrayRingProps) => {
const { nodes, materials } = useLoader<GLTFResult>( const lofTex = useLoader(THREE.TextureLoader, lofTexture);
GLTFLoader, const holeTex = useLoader(THREE.TextureLoader, holeTexture);
"/models/ring0.glb", const lifeTex = useLoader(THREE.TextureLoader, lifeTexture);
draco("/draco-gltf/")
const uniforms = useMemo(
() => ({
lof: { type: "t", value: lofTex },
hole: { type: "t", value: holeTex },
life: { type: "t", value: lifeTex },
}),
[lofTex, holeTex, lifeTex]
); );
// -0.27 const vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);
}
`;
const fragmentShader = `
varying vec2 vUv;
uniform sampler2D lof;
uniform sampler2D hole;
uniform sampler2D life;
// transform coordinates to uniform within segment
float tolocal(float x, int segments, float step) {
float period = 1.0/step*float(segments);
return mod(x, period) / period;
}
// check if coordinate is within the given height
bool isheight(float y, float thin) {
return y > 0.5-thin/2.0 && y < 0.5+thin/2.0;
}
// sloping function
float slope(float x, float thin) {
return x*(1.0-thin)/2.0;
}
// frag color / texture
// #424252 hex in original textures
vec4 color(vec2 vUv, int quadnum, bool textureexists, int thinperiod, int quadlen, float step) {
if (!textureexists) {
return vec4(0.259,0.259,0.322, 1);
} else if (quadnum % 2 == 1) {
return texture2D(hole, vec2(tolocal(vUv.x, quadlen-thinperiod, step), vUv.y));
} else if (quadnum == 0) {
return texture2D(lof, vec2(tolocal(vUv.x, quadlen-thinperiod, step), vUv.y));
} else {
return texture2D(life, vec2(tolocal(vUv.x, quadlen-thinperiod, step), vUv.y));
}
}
void main() {
// number of segments
float step = 64.0;
float thin = 0.3;
// segment within circle
int segment = int(floor(vUv.x * step));
int quadlen = int(step)/4;
// segment within circle's quad
int quadel = int(segment) % quadlen;
// which quad
int quadnum = int(segment) / quadlen;
// how big thin part is
int thinperiod = 12;
if (quadel < thinperiod && isheight(vUv.y, thin)) {
// thin line
gl_FragColor = color(vUv, quadnum, false, thinperiod, quadlen, step);
} else if (quadel == thinperiod) {
// slope up
float dist = tolocal(vUv.x, 1, step);
if (vUv.y > slope(1.0-dist, thin) && vUv.y < 1.0-slope(1.0-dist, thin)) {
gl_FragColor = color(vUv, quadnum, true, thinperiod, quadlen, step);
} else {
gl_FragColor = vec4(0, 0, 0, 0);
}
} else if (quadel == quadlen-1) {
// slope down
float dist = tolocal(vUv.x, 1, step);
if (vUv.y > slope(dist, thin) && vUv.y < 1.0-slope(dist, thin)) {
gl_FragColor = color(vUv, quadnum, true, thinperiod, quadlen, step);
} else {
gl_FragColor = vec4(0, 0, 0, 0);
}
} else if (quadel > thinperiod) {
gl_FragColor = color(vUv, quadnum, true, thinperiod, quadlen, step);
} else {
// transparent
gl_FragColor = vec4(0, 0, 0, 0);
}
}
`;
return ( return (
<group <mesh
scale={[1.3, 1.3, 1.3]}
position={[0, props.grayRingPosY, 0]} position={[0, props.grayRingPosY, 0]}
rotation={[0, 2.6, 0]} rotation={[0, 3.7, 0]}
renderOrder={1}
scale={[5, 2.5, 5]}
> >
<mesh <cylinderBufferGeometry
geometry={nodes.LainRing.geometry} args={[0.25, 0.25, 0.027, 64, 64, true]}
rotation={[0, Math.PI / 4, 0]} attach="geometry"
material={materials.RingTexture} />
></mesh> <shaderMaterial
</group> attach="material"
side={THREE.DoubleSide}
vertexShader={vertexShader}
fragmentShader={fragmentShader}
transparent={true}
uniforms={uniforms}
/>
</mesh>
); );
}); });

View file

@ -119,7 +119,7 @@ const HUDElement = memo((props: HUDElementProps) => {
); );
return ( return (
<group visible={props.hudVisibility}> <group visible={props.hudVisibility} renderOrder={1}>
<a.sprite <a.sprite
position-x={longHUDPosX} position-x={longHUDPosX}
position-y={currentSpriteHUD["long"]["position"][1]} position-y={currentSpriteHUD["long"]["position"][1]}

View file

@ -17,25 +17,25 @@ const Hub = memo(() => {
<GrayRing grayRingPosY={1.6} /> <GrayRing grayRingPosY={1.6} />
<PurpleRing purpleRingPosY={0.4} /> <PurpleRing purpleRingPosY={0.4} />
<GrayRing grayRingPosY={-0.27} /> <GrayRing grayRingPosY={-0.27} />
{Object.values(level_sprites).map((sprite) => { {/*{Object.values(level_sprites).map((sprite) => {*/}
return ( {/* return (*/}
<LevelSprite {/* <LevelSprite*/}
position={sprite.position as [number, number, number]} {/* position={sprite.position as [number, number, number]}*/}
scale={sprite.scale as [number, number, number]} {/* scale={sprite.scale as [number, number, number]}*/}
rotation={ {/* rotation={*/}
sprite.rotation as [ {/* sprite.rotation as [*/}
number, {/* number,*/}
number, {/* number,*/}
number, {/* number,*/}
(string | undefined)? {/* (string | undefined)?*/}
] {/* ]*/}
} {/* }*/}
sprite={sprite.sprite} {/* sprite={sprite.sprite}*/}
key={sprite.id} {/* key={sprite.id}*/}
active={sprite.id === currentSprite} {/* active={sprite.id === currentSprite}*/}
/> {/* />*/}
); {/* );*/}
})} {/*})}*/}
</Suspense> </Suspense>
</> </>
); );

View file

@ -92,6 +92,7 @@ const LevelSprite = memo((props: LevelSpriteConstructorProps) => {
position={props.position} position={props.position}
scale={props.scale} scale={props.scale}
rotation={props.rotation} rotation={props.rotation}
renderOrder={1}
> >
<planeBufferGeometry attach="geometry" /> <planeBufferGeometry attach="geometry" />
{props.active ? ( {props.active ? (

View file

@ -1,11 +1,8 @@
import React, { useMemo, useRef } from "react"; import React, {useMemo, useRef} from "react";
import { useFrame, useLoader } from "react-three-fiber"; import {useFrame, useLoader} from "react-three-fiber";
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import middleRingTexture from "../../static/sprites/middle_ring_tex.png"; import middleRingTexture from "../../static/sprites/middle_ring_tex.png";
import { draco } from "drei";
import * as THREE from "three"; import * as THREE from "three";
import { a, useSpring } from "@react-spring/three"; import {a, useSpring} from "@react-spring/three";
import { import {
middleRingNoiseAtom, middleRingNoiseAtom,
middleRingPosYAtom, middleRingPosYAtom,
@ -13,24 +10,9 @@ import {
middleRingRotXAtom, middleRingRotXAtom,
middleRingWobbleStrengthAtom, middleRingWobbleStrengthAtom,
} from "./MiddleRingAtom"; } from "./MiddleRingAtom";
import { useRecoilValue } from "recoil"; import {useRecoilValue} from "recoil";
type GLTFResult = GLTF & {
nodes: {
BezierCircle: THREE.Mesh;
};
materials: {
["Material.001"]: THREE.MeshStandardMaterial;
};
};
const MiddleRing = () => { const MiddleRing = () => {
const { nodes, materials } = useLoader<GLTFResult>(
GLTFLoader,
"/models/ring2.glb",
draco("/draco-gltf/")
);
const middleRingTex = useLoader(THREE.TextureLoader, middleRingTexture); const middleRingTex = useLoader(THREE.TextureLoader, middleRingTexture);
const middleRingWobbleStrength = useRecoilValue(middleRingWobbleStrengthAtom); const middleRingWobbleStrength = useRecoilValue(middleRingWobbleStrengthAtom);
@ -205,8 +187,7 @@ const MiddleRing = () => {
varying vec2 vUv; varying vec2 vUv;
void main() { void main() {
gl_FragColor = texture2D(tex, vUv); gl_FragColor = texture2D( tex, vUv);
gl_FragColor.a = 0.4;
} }
`; `;
@ -227,18 +208,18 @@ const MiddleRing = () => {
return ( return (
<a.mesh <a.mesh
material={materials["Material.001"]}
geometry={nodes.BezierCircle.geometry}
position={[0, 0, 0.3]} position={[0, 0, 0.3]}
position-y={middleRingPosState.middleRingPosY} position-y={middleRingPosState.middleRingPosY}
scale={[0.9, 0.7, 0.9]}
ref={middleRingRef} ref={middleRingRef}
rotation={[0, 0.9, 0]} rotation={[0, 0.9, 0]}
rotation-x={middleRingRotState.middleRingRotX} rotation-x={middleRingRotState.middleRingRotX}
> >
<cylinderBufferGeometry
args={[0.85, 0.85, 0.027, 64, 64, true]}
attach="geometry"
/>
<shaderMaterial <shaderMaterial
attach="material" attach="material"
color={0x8cffde}
side={THREE.DoubleSide} side={THREE.DoubleSide}
uniforms={uniforms} uniforms={uniforms}
vertexShader={vertexShader} vertexShader={vertexShader}

View file

@ -17,7 +17,7 @@ export const middleRingNoiseAtom = atom({
export const middleRingPosYAtom = atom({ export const middleRingPosYAtom = atom({
key: "middleRingPosYAtom", key: "middleRingPosYAtom",
default: -0.15, default: -0.11,
}); });
export const middleRingRotXAtom = atom({ export const middleRingRotXAtom = atom({

View file

@ -40,5 +40,12 @@
"rotation": [0, 0.09, 0], "rotation": [0, 0.09, 0],
"sprite": "Dc", "sprite": "Dc",
"id": "0513" "id": "0513"
},
"6": {
"position": [-0.9, 1.9, 1],
"scale": [0.25, 0.15, 0.25],
"rotation": [0, -0.5, 0],
"sprite": "Tda",
"id": "0515"
} }
} }