Skip to content

Instantly share code, notes, and snippets.

@whoisryosuke
Created May 27, 2022 00:24
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save whoisryosuke/e3e19de071e0ea5894fc72bede2b5936 to your computer and use it in GitHub Desktop.
Save whoisryosuke/e3e19de071e0ea5894fc72bede2b5936 to your computer and use it in GitHub Desktop.
Shader / GLSL / OpenGL - Inner border fragment shader. Resembles a "prototype" box for "grid"-like level debugging in game development.
import * as THREE from 'three'
import { useFrame, extend } from '@react-three/fiber'
import { useRef, useState } from 'react'
import useStore from '@/helpers/store'
import { shaderMaterial } from '@react-three/drei'
import { Mesh } from "three"
import vertex from './glsl/shader.vert'
import fragment from './glsl/shader.frag'
const ColorShiftMaterial = shaderMaterial(
{
time: 0,
color: new THREE.Color(0.05, 0.2, 0.025),
borderColor: new THREE.Color(0.15, 0.3, 0.025),
borderWidth: 0.1,
},
vertex,
fragment
)
// This is the 🔑 that HMR will renew if this file is edited
// It works for THREE.ShaderMaterial as well as for drei/shaderMaterial
// @ts-ignore
ColorShiftMaterial.key = THREE.MathUtils.generateUUID()
extend({ ColorShiftMaterial })
const Shader = (props: Mesh) => {
const meshRef = useRef(null)
const [hovered, setHover] = useState(false)
const router = useStore((state) => state.router)
useFrame((state, delta) => {
if (meshRef.current) {
meshRef.current.rotation.x = meshRef.current.rotation.y += 0.01
}
if (meshRef.current.material) {
meshRef.current.material.uniforms.time.value +=
Math.sin(delta / 2) * Math.cos(delta / 2)
}
})
return (
<mesh
ref={meshRef}
scale={hovered ? 1.1 : 1}
onClick={() => {
router.push(`/box`)
}}
onPointerOver={(e) => setHover(true)}
onPointerOut={(e) => setHover(false)}
{...props}
>
<boxBufferGeometry args={[1, 1, 1]} />
{/* @ts-ignore */}
<colorShiftMaterial key={ColorShiftMaterial.key} time={3} />
</mesh>
)
}
export default Shader
uniform vec3 color;
uniform vec3 borderColor;
uniform float borderWidth;
varying vec2 vUv;
void main() {
// We basically go through the X and Y values to see if they're less than the threshold
// UV goes from 0 to 1, so as X travels from 0 to 1
// we "limit" the color to when X is less than the borderWidth
// e.g. 0-0.1 = colored, 0.1-1.0 - not colored
// But we also get the opposite corners by taking the borderWidth and subtracting from 1.0 (the max)
if (vUv.x <= borderWidth || vUv.y <= borderWidth || vUv.x >= 1.0 - borderWidth || vUv.y >= 1.0 - borderWidth)
{
gl_FragColor.rgba = vec4(borderColor, 1.);
} else {
// And we "fill in" the "background" with another color
gl_FragColor.rgba = vec4(color, 1.);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment