Spaces:
Running
Running
| import { ShaderMaterial, Texture, Vector2, Vector3 } from "three"; | |
| import { useEffect, useMemo } from "react"; | |
| import { useThree } from "@react-three/fiber"; | |
| import { DEFAULT_CONFIG, REFRESH_RATE } from "../constant"; | |
| import baseVertex from "../glsl/base.vert?raw"; | |
| import clearFrag from "../glsl/clear.frag?raw"; | |
| import curlFrag from "../glsl/curl.frag?raw"; | |
| import divergenceFrag from "../glsl/divergence.frag?raw"; | |
| import gradientSubstractFrag from "../glsl/gradientSubstract.frag?raw"; | |
| import pressureFrag from "../glsl/pressure.frag?raw"; | |
| import splatFrag from "../glsl/splat.frag?raw"; | |
| import advectionFrag from "../glsl/advection.frag?raw"; | |
| import vorticityFrag from "../glsl/vorticity.frag?raw"; | |
| export const useMaterials = (): { [key: string]: ShaderMaterial } => { | |
| const size = useThree((s) => s.size); | |
| const shaderMaterials = useMemo(() => { | |
| const advection = new ShaderMaterial({ | |
| name: "Fluid/Advection", | |
| uniforms: { | |
| uVelocity: { | |
| value: new Texture(), | |
| }, | |
| uSource: { | |
| value: new Texture(), | |
| }, | |
| dt: { | |
| value: 1 / REFRESH_RATE, | |
| }, | |
| uDissipation: { | |
| value: 1.0, | |
| }, | |
| texelSize: { value: new Vector2() }, | |
| }, | |
| fragmentShader: advectionFrag, | |
| vertexShader: baseVertex, | |
| defines: { | |
| USE_V_UV: "", | |
| }, | |
| depthTest: false, | |
| depthWrite: false, | |
| }); | |
| const clear = new ShaderMaterial({ | |
| name: "Fluid/Clear", | |
| uniforms: { | |
| uTexture: { | |
| value: new Texture(), | |
| }, | |
| uClearValue: { | |
| value: DEFAULT_CONFIG.pressure, | |
| }, | |
| texelSize: { | |
| value: new Vector2(), | |
| }, | |
| }, | |
| fragmentShader: clearFrag, | |
| vertexShader: baseVertex, | |
| defines: { | |
| USE_V_UV: "", | |
| }, | |
| depthTest: false, | |
| depthWrite: false, | |
| }); | |
| const curl = new ShaderMaterial({ | |
| name: "Fluid/Curl", | |
| uniforms: { | |
| uVelocity: { | |
| value: new Texture(), | |
| }, | |
| texelSize: { | |
| value: new Vector2(), | |
| }, | |
| }, | |
| fragmentShader: curlFrag, | |
| vertexShader: baseVertex, | |
| defines: { | |
| USE_OFFSETS: "", | |
| }, | |
| depthTest: false, | |
| depthWrite: false, | |
| }); | |
| const divergence = new ShaderMaterial({ | |
| name: "Fluid/Divergence", | |
| uniforms: { | |
| uVelocity: { | |
| value: new Texture(), | |
| }, | |
| texelSize: { | |
| value: new Vector2(), | |
| }, | |
| }, | |
| fragmentShader: divergenceFrag, | |
| vertexShader: baseVertex, | |
| defines: { | |
| USE_V_UV: "", | |
| USE_OFFSETS: "", | |
| }, | |
| depthTest: false, | |
| depthWrite: false, | |
| }); | |
| const gradientSubstract = new ShaderMaterial({ | |
| name: "Fluid/GradientSubtract", | |
| uniforms: { | |
| uPressure: { | |
| value: new Texture(), | |
| }, | |
| uVelocity: { | |
| value: new Texture(), | |
| }, | |
| texelSize: { | |
| value: new Vector2(), | |
| }, | |
| }, | |
| fragmentShader: gradientSubstractFrag, | |
| vertexShader: baseVertex, | |
| defines: { | |
| USE_V_UV: "", | |
| USE_OFFSETS: "", | |
| }, | |
| depthTest: false, | |
| depthWrite: false, | |
| }); | |
| const pressure = new ShaderMaterial({ | |
| name: "Fluid/Pressure", | |
| uniforms: { | |
| uPressure: { | |
| value: new Texture(), | |
| }, | |
| uDivergence: { | |
| value: new Texture(), | |
| }, | |
| texelSize: { | |
| value: new Vector2(), | |
| }, | |
| }, | |
| fragmentShader: pressureFrag, | |
| vertexShader: baseVertex, | |
| defines: { | |
| USE_V_UV: "", | |
| USE_OFFSETS: "", | |
| }, | |
| depthTest: false, | |
| depthWrite: false, | |
| }); | |
| const splat = new ShaderMaterial({ | |
| name: "Fluid/Splat", | |
| uniforms: { | |
| uTarget: { | |
| value: new Texture(), | |
| }, | |
| aspectRatio: { | |
| value: size.width / size.height, | |
| }, | |
| uColor: { | |
| value: new Vector3(), | |
| }, | |
| uPointer: { | |
| value: new Vector2(), | |
| }, | |
| uRadius: { | |
| value: DEFAULT_CONFIG.radius / 100.0, | |
| }, | |
| texelSize: { | |
| value: new Vector2(), | |
| }, | |
| }, | |
| fragmentShader: splatFrag, | |
| vertexShader: baseVertex, | |
| defines: { | |
| USE_V_UV: "", | |
| }, | |
| depthTest: false, | |
| depthWrite: false, | |
| }); | |
| const vorticity = new ShaderMaterial({ | |
| name: "Fluid/Vorticity", | |
| uniforms: { | |
| uVelocity: { | |
| value: new Texture(), | |
| }, | |
| uCurl: { | |
| value: new Texture(), | |
| }, | |
| uCurlValue: { | |
| value: DEFAULT_CONFIG.curl, | |
| }, | |
| dt: { | |
| value: 1 / REFRESH_RATE, | |
| }, | |
| texelSize: { | |
| value: new Vector2(), | |
| }, | |
| }, | |
| fragmentShader: vorticityFrag, | |
| vertexShader: baseVertex, | |
| defines: { | |
| USE_V_UV: "", | |
| USE_OFFSETS: "", | |
| }, | |
| depthTest: false, | |
| depthWrite: false, | |
| }); | |
| return { | |
| splat, | |
| curl, | |
| clear, | |
| divergence, | |
| pressure, | |
| gradientSubstract, | |
| advection, | |
| vorticity, | |
| }; | |
| }, [size]); | |
| useEffect(() => { | |
| for (const material of Object.values(shaderMaterials)) { | |
| const aspectRatio = size.width / (size.height + 400); | |
| material.uniforms.texelSize.value.set( | |
| 1 / (DEFAULT_CONFIG.simRes * aspectRatio), | |
| 1 / DEFAULT_CONFIG.simRes, | |
| ); | |
| } | |
| return () => { | |
| for (const material of Object.values(shaderMaterials)) { | |
| material.dispose(); | |
| } | |
| }; | |
| }, [shaderMaterials, size]); | |
| return shaderMaterials; | |
| }; | |