Created
May 27, 2022 02:04
-
-
Save whoisryosuke/e9c5aa46ce60125d9ea0bb4cdb90fa6a to your computer and use it in GitHub Desktop.
Shader / GLSL / OpenGL - Inner border fragment shader (better version with lighter grid inside). Resembles a "prototype" box for "grid"-like level debugging in game development.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as THREE from 'three' | |
import { useFrame, extend, MeshProps } from '@react-three/fiber' | |
import { useRef, useState } from 'react' | |
import useStore from '@/helpers/store' | |
import { shaderMaterial } from '@react-three/drei' | |
import { Color, Mesh } from "three" | |
import vertex from './glsl/shader.vert' | |
import fragment from './glsl/shader.frag' | |
const ColorShiftMaterial = shaderMaterial( | |
{ | |
time: 0, | |
color: new THREE.Color(8/255, 108/255, 149/255), | |
borderColor: new THREE.Color(0.9,0.9,0.9), | |
borderWidth: 0.1, | |
gridSize: 0.1, | |
gridWidth: 0.05, | |
}, | |
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 }) | |
type Props = Partial<MeshProps> & { | |
color: Color; | |
borderColor: Color; | |
} | |
const Shader = ({ | |
color, | |
borderColor, | |
...props | |
}: Props) => { | |
const meshRef = useRef(null) | |
console.log('color', color) | |
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) | |
} | |
if(meshRef.current.material && color) { | |
meshRef.current.material.uniforms.color.value = color; | |
} | |
if(meshRef.current.material && borderColor) { | |
meshRef.current.material.uniforms.borderColor.value = borderColor; | |
} | |
}) | |
return ( | |
<mesh | |
ref={meshRef} | |
{...props} | |
> | |
<boxBufferGeometry args={[1, 1, 1]} /> | |
{/* @ts-ignore */} | |
<colorShiftMaterial key={ColorShiftMaterial.key} time={3} /> | |
</mesh> | |
) | |
} | |
export default Shader |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as THREE from 'three' | |
import dynamic from 'next/dynamic' | |
// import Shader from '@/components/canvas/Shader/Shader' | |
// Dynamic import is used to prevent a payload when the website start that will include threejs r3f etc.. | |
// WARNING ! errors might get obfuscated by using dynamic import. | |
// If something goes wrong go back to a static import to show the error. | |
// https://github.com/pmndrs/react-three-next/issues/49 | |
const Shader = dynamic(() => import('@/components/canvas/Shader/Shader'), { | |
ssr: false, | |
}) | |
// dom components goes here | |
const DOM = () => { | |
return ( | |
<></> | |
) | |
} | |
// canvas components goes here | |
const R3F = ({r3f = true}) => { | |
return ( | |
<> | |
<Shader | |
color={new THREE.Color(8/255, 108/255, 149/255)} | |
borderColor={new THREE.Color(0.9,0.9,0.9)} | |
position={[-1,0,0]} | |
/> | |
<Shader | |
color={new THREE.Color(149/255, 108/255, 8/255)} | |
borderColor={new THREE.Color(0.9,0.9,0.9)} | |
position={[1,0,0]} | |
/> | |
</> | |
) | |
} | |
const Page = () => { | |
return ( | |
<> | |
<DOM /> | |
<R3F r3f /> | |
</> | |
) | |
} | |
export default Page | |
export async function getStaticProps() { | |
return { | |
props: { | |
title: 'Index', | |
}, | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
uniform vec3 color; | |
uniform vec3 borderColor; | |
uniform float borderWidth; | |
uniform float gridSize; | |
uniform float gridWidth; | |
varying vec2 vUv; | |
float grid(vec2 st, float res) | |
{ | |
vec2 grid = fract(st*res); | |
return (step(res,grid.x) * step(res,grid.y)); | |
} | |
void main() { | |
vec3 red = vec3(1,0,0); | |
vec4 finalColor; | |
// 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) | |
{ | |
finalColor = vec4(borderColor, 1.); | |
} else { | |
// And we "fill in" the "background" with another color | |
finalColor = vec4(color, 1.); | |
} | |
// UV goes from 0-1, so we need to break it up into a grid | |
// We do that by "dividing" 1 by the number of grid segments we need (e.g. 2 for 2x2 grid) | |
if(fract(vUv.x / gridSize) < gridWidth || fract(vUv.y / gridSize) < gridWidth) | |
finalColor = finalColor / vec4(0.9,0.9,0.9, 1); | |
// This makes a small square 1/4 the size (but fills color inversely? if that makes sense) | |
// if (vUv.x* 2.0 <= borderWidth || vUv.y* 2.0 <= borderWidth || vUv.x* 2.0 >= 1.0 - borderWidth || vUv.y* 2.0 >= 1.0 - borderWidth) | |
// { | |
// // finalColor = vec4(borderColor * vec3(0.3,0.3,0.3), 1.); | |
// finalColor = vec4(red, 1.); | |
// } | |
gl_FragColor.rgba = finalColor; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment