Skip to content

Instantly share code, notes, and snippets.

@increpare
Created November 21, 2025 22:24
Show Gist options
  • Select an option

  • Save increpare/f041d9a4f44e5420a8d9b0add93e6038 to your computer and use it in GitHub Desktop.

Select an option

Save increpare/f041d9a4f44e5420a8d9b0add93e6038 to your computer and use it in GitHub Desktop.
shader_type canvas_item;
render_mode blend_mix; // Changed from blend_add for better visibility of text
uniform float strength = 20.0; // Reduced default strength for text
uniform float time_scale = 1.0;
uniform float time_offset = 0.0; // To randomize start
// Simple 2D noise function
vec2 hash(vec2 p) {
p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));
return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);
}
float noise(vec2 p) {
const float K1 = 0.366025404; // (sqrt(3)-1)/2;
const float K2 = 0.211324865; // (3-sqrt(3))/6;
vec2 i = floor(p + (p.x + p.y) * K1);
vec2 a = p - i + (i.x + i.y) * K2;
vec2 o = (a.x > a.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
vec2 b = a - o + K2;
vec2 c = a - 1.0 + 2.0 * K2;
vec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0);
vec3 n = h * h * h * h * vec3(dot(a, hash(i + 0.0)), dot(b, hash(i + o)), dot(c, hash(i + 1.0)));
return dot(n, vec3(70.0));
}
// Fractional Brownian Motion for turbulence
float fbm(vec2 p) {
float f = 0.0;
float w = 0.5;
for (int i = 0; i < 3; i++) {
f += w * noise(p);
p *= 2.0;
w *= 0.5;
}
return f;
}
void vertex() {
float t = TIME * time_scale + time_offset;
// Use vertex position and time to sample noise field
// Scale the coordinates to control the frequency of the "eddies"
vec2 noise_coord = vec2(VERTEX.x * 0.01, VERTEX.y * 0.01 - t * 0.2);
// Sample turbulence fields
float turb_x = fbm(noise_coord);
float turb_y = fbm(noise_coord + vec2(100.0, 100.0)); // Offset for decorrelated Y motion
// Primary "wind" direction that shifts over time
float wind_dir = sin(t * 0.5 + VERTEX.y * 0.001);
float x_offset = (turb_x * 2.0 + wind_dir * 1.0);
float y_offset = (turb_y * 1.5 - abs(wind_dir) * 0.5);
// Add a "wafting" sine wave
x_offset += sin(t * 1.5 + VERTEX.y * 0.01) * 0.5;
// Scale strength by vertex alpha for fade effect
float effective_strength = strength * (0.3+COLOR.b/5.0);
// Apply the offset
VERTEX.x += x_offset * effective_strength;
VERTEX.y += y_offset * effective_strength;
// Slight rotation/shear
// float rot_angle = turb_x * 0.1;
// float s = sin(rot_angle);
// float c = cos(rot_angle);
// mat2 rot = mat2(vec2(c, -s), vec2(s, c));
// VERTEX = rot * VERTEX;
}
void fragment() {
// Optional: erode alpha based on noise for extra smokiness
float t = TIME * time_scale + time_offset;
float noise_val = fbm(UV * 5.0 + vec2(0.0, -t * 0.2));
// Make the edges wispy
// COLOR.a *= smoothstep(0.2, 0.8, noise_val + 0.5);
// Just basic transparency preservation + slight noise modulation
COLOR.a *= 0.8 + 0.2 * noise_val;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment