Skip to content

Instantly share code, notes, and snippets.

@josippapez
Created January 31, 2025 09:18
Show Gist options
  • Select an option

  • Save josippapez/b14933d96c5ec610de641d95bfc002e4 to your computer and use it in GitHub Desktop.

Select an option

Save josippapez/b14933d96c5ec610de641d95bfc002e4 to your computer and use it in GitHub Desktop.
Moving Blobs shader
const MovingBlobsBackground = () => {
const shaderRef = useRef<ShaderMaterial>(null!)
useFrame((state) => {
if (shaderRef.current) {
shaderRef.current.uniforms.uTime.value = state.clock.elapsedTime
}
})
return (
<mesh position={[0, 0, 1]}>
<planeGeometry args={[2, 2]} />
<shaderMaterial
ref={shaderRef}
fragmentShader={`
uniform float uTime;
float random(vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
// Simplex 2D noise
vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); }
float snoise(vec2 v){
const vec4 C = vec4(0.211324865405187, 0.366025403784439,
-0.577350269189626, 0.024390243902439);
vec2 i = floor(v + dot(v, C.yy) );
vec2 x0 = v - i + dot(i, C.xx);
vec2 i1;
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
vec4 x12 = x0.xyxy + C.xxzz;
x12.xy -= i1;
i = mod(i, 289.0);
vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
+ i.x + vec3(0.0, i1.x, 1.0 ));
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy),
dot(x12.zw,x12.zw)), 0.0);
m = m*m ;
m = m*m ;
vec3 x = 2.0 * fract(p * C.www) - 1.0;
vec3 h = abs(x) - 0.5;
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;
m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
vec3 g;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g);
}
void main() {
vec2 uv = gl_FragCoord.xy / vec2(1000.0);
// Create multiple layers of noise for ice structure
float n1 = snoise(uv * 3.0 + uTime * 0.05);
float n2 = snoise(uv * 6.0 - uTime * 0.03);
float n3 = snoise(uv * 9.0 + uTime * 0.02);
// Combine noise layers
float finalNoise = (n1 * 0.5 + n2 * 0.3 + n3 * 0.2);
// Create ice pattern threshold
float iceThreshold = 0.5;
float pattern = smoothstep(0.3, 0.7, finalNoise);
// Determine if current pixel is ice or background
bool isIce = pattern > iceThreshold;
vec3 color;
float alpha;
if (isIce) {
// Ice areas - translucent and grainy
vec3 baseColor = vec3(0.85, 0.92, 1.0);
vec3 secondaryColor = vec3(0.75, 0.85, 0.95);
color = mix(baseColor, secondaryColor, pattern);
// Add grain only to ice
float grain = random(uv * uTime) * 0.03;
color += vec3(grain);
// Make ice translucent
alpha = mix(0.6, 0.8, pattern);
} else {
// Non-ice areas - solid black
color = vec3(0.0);
alpha = 1.0;
}
gl_FragColor = vec4(color, alpha);
}
`}
vertexShader={`
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`}
uniforms={{
uTime: { value: 0 },
}}
transparent={true}
/>
</mesh>
)
}
@josippapez
Copy link
Author

Screenshot 2025-01-31 at 10 17 53

@josippapez
Copy link
Author

Same but smaller blobs

<mesh position={[0, 0, 1]}> <planeGeometry args={[2, 2]} /> <shaderMaterial ref={shaderRef} fragmentShader={
float random(vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
}

      // Simplex 2D noise
      vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); }

      float snoise(vec2 v){
        const vec4 C = vec4(0.211324865405187, 0.366025403784439,
                 -0.577350269189626, 0.024390243902439);
        vec2 i  = floor(v + dot(v, C.yy) );
        vec2 x0 = v -   i + dot(i, C.xx);
        vec2 i1;
        i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
        vec4 x12 = x0.xyxy + C.xxzz;
        x12.xy -= i1;
        i = mod(i, 289.0);
        vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
        + i.x + vec3(0.0, i1.x, 1.0 ));
        vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy),
          dot(x12.zw,x12.zw)), 0.0);
        m = m*m ;
        m = m*m ;
        vec3 x = 2.0 * fract(p * C.www) - 1.0;
        vec3 h = abs(x) - 0.5;
        vec3 ox = floor(x + 0.5);
        vec3 a0 = x - ox;
        m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
        vec3 g;
        g.x  = a0.x  * x0.x  + h.x  * x0.y;
        g.yz = a0.yz * x12.xz + h.yz * x12.yw;
        return 130.0 * dot(m, g);
      }

      void main() {
        vec2 uv = gl_FragCoord.xy / vec2(1000.0);

        // Create multiple layers of noise with higher frequencies
        float n1 = snoise(uv * 30.0);
        float n2 = snoise(uv * 40.0);
        float n3 = snoise(uv * 50.0);
        float n4 = snoise(uv * 60.0);
        float n5 = snoise(uv * 70.0);

        // Combine noise layers for more detailed pattern
        float finalNoise = (n1 * 0.3 + n2 * 0.25 + n3 * 0.2 + n4 * 0.15 + n5 * 0.1);

        // Create more scattered, point-like blobs
        float blobThreshold = 0.5;
        float pattern = smoothstep(0.45, 0.55, finalNoise);

        // Add fine grain structure
        float baseGrain = random(uv * 2.0) * 0.15;
        float detailGrain = random(uv * 10.0) * 0.1;
        float combinedGrain = baseGrain + detailGrain;

        vec3 color;
        float alpha;

        // Create point-like effect
        bool isPoint = (pattern + combinedGrain) > blobThreshold;

        if (isPoint) {
          // Point areas - create grainy, scattered effect
          vec3 baseColor = vec3(0.9, 0.95, 1.0);
          vec3 grainColor = vec3(0.7, 0.8, 0.9);

          // Mix colors based on noise and grain
          color = mix(baseColor, grainColor, combinedGrain);

          // Add sparkle effect
          float sparkle = pow(random(uv * 50.0), 3.0) * 0.5;
          color += vec3(sparkle);

          // Vary transparency for depth effect
          alpha = mix(0.1, 0.3, pattern * (1.0 - combinedGrain));
        } else {
          color = vec3(0.0);
          alpha = 1.0;
        }

        gl_FragColor = vec4(color, alpha);
      }
    `}
    vertexShader={`
      void main() {
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      }
    `}
    uniforms={{}}
    transparent={true}
  />
</mesh>`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment