diff --git a/src/components/3D/BorderPlane/index.jsx b/src/components/3D/BorderPlane/index.jsx new file mode 100644 index 0000000..a2c7c37 --- /dev/null +++ b/src/components/3D/BorderPlane/index.jsx @@ -0,0 +1,107 @@ +/* eslint-disable no-unused-vars */ +/* eslint-disable react/prop-types */ +/* eslint-disable react/no-unknown-property */ +import { useLayoutEffect, useMemo, useRef } from "react"; +import { useFrame, useThree } from "@react-three/fiber"; +import { DoubleSide, RawShaderMaterial, Color, Vector2 } from "three"; + +const vertexShader = ` +varying vec2 vUv; +attribute vec3 normal; +attribute vec3 position; +attribute vec2 uv; + +uniform mat4 projectionMatrix; +uniform mat4 viewMatrix; +uniform mat4 modelMatrix; + +varying vec3 vNormal; + +void main() { + vUv = uv; + gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0); +} +`; +const fragmentShader = ` +precision highp float; +varying vec2 vUv; + +uniform vec3 uBorderColor; +uniform float uBorderWidth; +uniform vec2 uResolution; +uniform vec2 uSize; + +void main() { + vec2 p = vUv * uSize; + float border = 0.0; + + if (p.x < uBorderWidth / 2.0 || p.x > uSize.x - uBorderWidth / 2.0 || + p.y < uBorderWidth / 2.0 || p.y > uSize.y - uBorderWidth / 2.0) { + border = 1.0; + } + + gl_FragColor = vec4( uBorderColor, border); + +} +`; + +export const BorderPlane = ({ + planeSize = [10, 10], + color = "#ffffff", + ...props +}) => { + const { size } = useThree(); + + const ref = useRef(); + + const uniforms = useMemo(() => { + return { + uTime: { value: 0 }, + uBorderColor: { value: new Color(0xffffff) }, + uBorderWidth: { value: 10 }, + uResolution: { value: new Vector2() }, + uSize: { value: new Vector2(20, 20) }, + }; + }, []); + + useLayoutEffect(() => { + ref.current.material.uniforms.uResolution.value.x = size.width; + ref.current.material.uniforms.uResolution.value.y = size.height; + }, [size]); + + useLayoutEffect(() => { + ref.current.material.uniforms.uSize.value.x = planeSize[0]; + ref.current.material.uniforms.uSize.value.y = planeSize[1]; + }, [planeSize]); + + useLayoutEffect(() => { + // ref.current.material.uniforms.uBorderColor.value = color; + }, [color]); + + const planeMaterial = useMemo(() => { + return new RawShaderMaterial({ + vertexShader, + fragmentShader, + uniforms, + transparent: true, + visible: true, + side: DoubleSide, + }); + }, [uniforms]); + + // useFrame(({ clock }) => { + // const { elapsedTime } = clock; + // planeMaterial.uniforms.uTime.value = elapsedTime; + // }); + + return ( + + + + ); +}; diff --git a/src/components/3D/Scene.jsx b/src/components/3D/Scene.jsx index 6042b1c..47bc9d8 100644 --- a/src/components/3D/Scene.jsx +++ b/src/components/3D/Scene.jsx @@ -22,6 +22,7 @@ import { } from "../../utils"; import { ChangeColor } from "./ChangeColor"; import { useStore } from "../../store"; +import { BorderPlane } from "./BorderPlane"; export const Scene = () => { const [bricks, setBricks] = useState([]); @@ -206,6 +207,11 @@ export const Scene = () => { dimensions={{ x: width, z: depth }} translation={{ x: anchorX, z: anchorZ }} /> + {/* */} ); };