-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlava_visual.py
More file actions
131 lines (109 loc) · 4.63 KB
/
lava_visual.py
File metadata and controls
131 lines (109 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import moderngl
import moderngl_window
from moderngl_window import geometry
import math
class LavaShader(moderngl_window.WindowConfig):
"""🔥 RTX Lava Shader — seamless & 3D-like version"""
title = "🔥 Seamless 3D Lava Shader"
gl_version = (3, 3)
window_size = (1280, 720)
aspect_ratio = None
resizable = True
resource_dir = '.'
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.quad = geometry.quad_fs()
self.prog = self.ctx.program(
vertex_shader="""
#version 330
in vec2 in_position;
out vec2 v_uv;
void main() {
v_uv = in_position * 0.5 + 0.5;
gl_Position = vec4(in_position, 0.0, 1.0);
}
""",
fragment_shader="""
#version 330
uniform vec2 u_res;
uniform float u_time;
uniform vec2 u_mouse;
in vec2 v_uv;
out vec4 fragColor;
// --- Smooth Noise ---
float hash(vec2 p) {
p = fract(p * vec2(123.34, 456.21));
p += dot(p, p + 78.233);
return fract(p.x * p.y);
}
float noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
vec2 u = f * f * (3.0 - 2.0 * f);
float a = hash(i + vec2(0.0,0.0));
float b = hash(i + vec2(1.0,0.0));
float c = hash(i + vec2(0.0,1.0));
float d = hash(i + vec2(1.0,1.0));
return mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
}
float fbm(vec2 p) {
float v = 0.0;
float a = 0.5;
for(int i = 0; i < 6; i++) {
v += a * noise(p);
p *= 2.0;
a *= 0.5;
}
return v;
}
vec3 palette(float t) {
vec3 black = vec3(0.02, 0.01, 0.005);
vec3 red = vec3(0.6, 0.04, 0.0);
vec3 orange = vec3(1.0, 0.45, 0.1);
vec3 yellow = vec3(1.0, 0.85, 0.35);
if(t < 0.35) return mix(black, red, smoothstep(0.0,0.35,t));
else if(t < 0.7) return mix(red, orange, smoothstep(0.35,0.7,t));
else return mix(orange, yellow, smoothstep(0.7,1.0,t));
}
void main() {
vec2 uv = v_uv * 2.0 - 1.0;
uv.x *= u_res.x / u_res.y;
float t = u_time * 0.35;
// Use sine warp to make motion seamless
vec2 motion = vec2(
fbm(uv * 2.0 + vec2(t*0.3, t*0.15)),
fbm(uv * 2.0 + vec2(-t*0.25, t*0.4))
);
// Scroll pattern
vec2 p = uv * 2.5 + motion * 1.2;
float n = fbm(p + vec2(t*0.7, -t*0.3));
// Add layered detail
n += 0.25 * fbm(p * 3.0 + vec2(-t*0.2, t*0.3));
// Mouse interaction
vec2 m = u_mouse / u_res * 2.0 - 1.0;
m.x *= u_res.x / u_res.y;
n += 0.15 * exp(-8.0 * distance(uv, m));
// Fake 3D shading (based on gradient)
vec3 base = palette(n);
float depth = smoothstep(0.2, 0.8, n);
vec3 normal = normalize(vec3(dFdx(n), dFdy(n), 0.4));
vec3 lightDir = normalize(vec3(0.4, 0.6, 0.9));
float diff = max(dot(normal, lightDir), 0.0);
vec3 col = base * (0.3 + 0.7 * diff);
fragColor = vec4(pow(col, vec3(1.2)), 1.0);
}
""",
)
self.time = 0.0
self.mouse = (0.5, 0.5)
def on_render(self, time: float, frame_time: float):
self.time += frame_time
self.ctx.clear(0.0, 0.0, 0.0)
self.prog['u_res'].value = self.window_size
self.prog['u_time'].value = self.time
self.prog['u_mouse'].value = self.mouse
self.quad.render(self.prog)
def on_mouse_motion(self, x, y, dx, dy):
self.mouse = (x, self.window_size[1] - y)
if __name__ == "__main__":
moderngl_window.run_window_config(LavaShader)