mlabonne's picture
upload demo files (#1)
01488bc
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;
};