feat: add net shader

This commit is contained in:
math-pixel
2026-05-13 17:07:12 +02:00
parent f5d3d080c8
commit 6399a2f89f
3 changed files with 92 additions and 1 deletions
+25
View File
@@ -0,0 +1,25 @@
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from "three";
import { createNetShader } from "@/shaders/NetShader";
export function NetTest(): React.JSX.Element {
const materialRef = useRef<THREE.ShaderMaterial>(null);
useFrame((_, delta) => {
if (materialRef.current) {
materialRef.current.uniforms.uTime.value += delta;
}
});
return (
<mesh position={[0, 2, -5]}>
<planeGeometry args={[2, 2, 1, 1]} />
<primitive
object={createNetShader()}
ref={materialRef}
attach="material"
/>
</mesh>
);
}
+62
View File
@@ -0,0 +1,62 @@
import { ShaderMaterial } from "three";
export const createNetShader = (): ShaderMaterial => {
return new ShaderMaterial({
transparent: true,
depthWrite: false,
uniforms: {
uTime: { value: 0 },
uGridScale: { value: 15.0 },
uPincushionStrength: { value: 0.4 },
uBloomIntensity: { value: 0.8 },
uGridThickness: { value: 0.05 },
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform float uTime;
uniform float uGridScale;
uniform float uPincushionStrength;
uniform float uBloomIntensity;
uniform float uGridThickness;
varying vec2 vUv;
vec2 applyPincushion(vec2 uv, float strength) {
vec2 center = uv - 0.5;
float dist = length(center);
float distortion = 1.0 + dist * dist * strength;
return center * distortion + 0.5;
}
float grid(vec2 uv, float scale, float thickness) {
vec2 gridUV = fract(uv * scale);
float edgeX = step(gridUV.x, thickness) + step(1.0 - thickness, gridUV.x);
float edgeY = step(gridUV.y, thickness) + step(1.0 - thickness, gridUV.y);
float line = min(edgeX + edgeY, 1.0);
return line;
}
void main() {
vec2 uv = applyPincushion(vUv, uPincushionStrength);
float gridPattern = grid(uv, uGridScale, uGridThickness);
vec3 gridColor = vec3(1.0, 0.4, 0.7);
float bloom = gridPattern * uBloomIntensity;
vec3 col = gridColor * (0.3 + bloom);
gl_FragColor = vec4(col, gridPattern * 0.95);
}
`,
});
};
+4
View File
@@ -28,6 +28,7 @@ import { GameMap } from "@/world/GameMap";
import { GameStageContent } from "@/world/GameStageContent"; import { GameStageContent } from "@/world/GameStageContent";
import { Player } from "@/world/player/Player"; import { Player } from "@/world/player/Player";
import { TestMap } from "@/world/debug/TestMap"; import { TestMap } from "@/world/debug/TestMap";
import { NetTest } from "@/components/three/NetTest";
import type { SceneLoadingChangeHandler } from "@/types/world/sceneLoading"; import type { SceneLoadingChangeHandler } from "@/types/world/sceneLoading";
interface WorldProps { interface WorldProps {
@@ -98,7 +99,10 @@ export function World({ onLoadingStateChange }: WorldProps): React.JSX.Element {
) : null} ) : null}
</> </>
) : ( ) : (
<>
<TestMap onOctreeReady={handleOctreeReady} /> <TestMap onOctreeReady={handleOctreeReady} />
<NetTest />
</>
)} )}
{sceneMode !== "game" && spawnPlayer ? ( {sceneMode !== "game" && spawnPlayer ? (