glplot 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- glplot/__init__.py +6 -0
- glplot/backend.py +15 -0
- glplot/controllers.py +69 -0
- glplot/core/__init__.py +0 -0
- glplot/core/context.py +50 -0
- glplot/core/layers.py +163 -0
- glplot/core/legacy.py +98 -0
- glplot/engine.py +1270 -0
- glplot/managers/__init__.py +0 -0
- glplot/managers/axis.py +66 -0
- glplot/managers/effects.py +343 -0
- glplot/managers/hud.py +510 -0
- glplot/managers/hud_state.py +95 -0
- glplot/managers/picking.py +174 -0
- glplot/managers/renderer_manager.py +158 -0
- glplot/options.py +120 -0
- glplot/policy.py +108 -0
- glplot/pyplot.py +735 -0
- glplot/renderers/__init__.py +0 -0
- glplot/renderers/axis.py +126 -0
- glplot/renderers/base.py +40 -0
- glplot/renderers/density.py +120 -0
- glplot/renderers/exact.py +215 -0
- glplot/renderers/interaction.py +77 -0
- glplot/renderers/line_family.py +250 -0
- glplot/renderers/patch.py +149 -0
- glplot/renderers/polyline.py +230 -0
- glplot/renderers/scatter.py +185 -0
- glplot/renderers/text.py +72 -0
- glplot/scratch/__init__.py +0 -0
- glplot/utils/__init__.py +0 -0
- glplot/utils/export.py +112 -0
- glplot/utils/gl_utils.py +32 -0
- glplot/utils/mpl_bridge.py +60 -0
- glplot/utils/shaders.py +889 -0
- glplot-0.1.0.dist-info/METADATA +75 -0
- glplot-0.1.0.dist-info/RECORD +39 -0
- glplot-0.1.0.dist-info/WHEEL +4 -0
- glplot-0.1.0.dist-info/licenses/LICENSE +0 -0
glplot/utils/shaders.py
ADDED
|
@@ -0,0 +1,889 @@
|
|
|
1
|
+
# --- SHARED UTILS ---
|
|
2
|
+
|
|
3
|
+
HEATMAP_FUNCS = r"""
|
|
4
|
+
vec3 heatmap_classic(float x) {
|
|
5
|
+
x = clamp(x, 0.0, 1.0);
|
|
6
|
+
return vec3(
|
|
7
|
+
smoothstep(0.0, 0.3, x),
|
|
8
|
+
smoothstep(0.3, 0.6, x),
|
|
9
|
+
smoothstep(0.6, 1.0, x)
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
vec3 heatmap_viridis_like(float x) {
|
|
14
|
+
x = clamp(x, 0.0, 1.0);
|
|
15
|
+
vec3 c0 = vec3(0.267, 0.005, 0.329);
|
|
16
|
+
vec3 c1 = vec3(0.283, 0.141, 0.458);
|
|
17
|
+
vec3 c2 = vec3(0.254, 0.265, 0.530);
|
|
18
|
+
vec3 c3 = vec3(0.207, 0.372, 0.553);
|
|
19
|
+
vec3 c4 = vec3(0.164, 0.471, 0.558);
|
|
20
|
+
vec3 c5 = vec3(0.128, 0.567, 0.551);
|
|
21
|
+
vec3 c6 = vec3(0.135, 0.659, 0.518);
|
|
22
|
+
vec3 c7 = vec3(0.267, 0.749, 0.441);
|
|
23
|
+
vec3 c8 = vec3(0.478, 0.821, 0.318);
|
|
24
|
+
vec3 c9 = vec3(0.741, 0.873, 0.150);
|
|
25
|
+
|
|
26
|
+
if (x < 0.11) return mix(c0, c1, x / 0.11);
|
|
27
|
+
if (x < 0.22) return mix(c1, c2, (x - 0.11) / 0.11);
|
|
28
|
+
if (x < 0.33) return mix(c2, c3, (x - 0.22) / 0.11);
|
|
29
|
+
if (x < 0.44) return mix(c3, c4, (x - 0.33) / 0.11);
|
|
30
|
+
if (x < 0.55) return mix(c4, c5, (x - 0.44) / 0.11);
|
|
31
|
+
if (x < 0.66) return mix(c5, c6, (x - 0.55) / 0.11);
|
|
32
|
+
if (x < 0.77) return mix(c6, c7, (x - 0.66) / 0.11);
|
|
33
|
+
if (x < 0.88) return mix(c7, c8, (x - 0.77) / 0.11);
|
|
34
|
+
return mix(c8, c9, (x - 0.88) / 0.12);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
vec3 heatmap_plasma_like(float x) {
|
|
38
|
+
x = clamp(x, 0.0, 1.0);
|
|
39
|
+
vec3 c0 = vec3(0.050, 0.030, 0.528);
|
|
40
|
+
vec3 c1 = vec3(0.291, 0.071, 0.718);
|
|
41
|
+
vec3 c2 = vec3(0.507, 0.104, 0.749);
|
|
42
|
+
vec3 c3 = vec3(0.692, 0.165, 0.564);
|
|
43
|
+
vec3 c4 = vec3(0.845, 0.277, 0.388);
|
|
44
|
+
vec3 c5 = vec3(0.954, 0.468, 0.199);
|
|
45
|
+
vec3 c6 = vec3(0.940, 0.975, 0.131);
|
|
46
|
+
|
|
47
|
+
if (x < 0.16) return mix(c0, c1, x / 0.16);
|
|
48
|
+
if (x < 0.32) return mix(c1, c2, (x - 0.16) / 0.16);
|
|
49
|
+
if (x < 0.48) return mix(c2, c3, (x - 0.32) / 0.16);
|
|
50
|
+
if (x < 0.64) return mix(c3, c4, (x - 0.48) / 0.16);
|
|
51
|
+
if (x < 0.80) return mix(c4, c5, (x - 0.64) / 0.16);
|
|
52
|
+
return mix(c5, c6, (x - 0.80) / 0.20);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
vec3 heatmap_inferno(float x) {
|
|
56
|
+
x = clamp(x, 0.0, 1.0);
|
|
57
|
+
vec3 c0 = vec3(0.000, 0.000, 0.016);
|
|
58
|
+
vec3 c1 = vec3(0.073, 0.038, 0.201);
|
|
59
|
+
vec3 c2 = vec3(0.243, 0.053, 0.404);
|
|
60
|
+
vec3 c3 = vec3(0.449, 0.111, 0.437);
|
|
61
|
+
vec3 c4 = vec3(0.665, 0.177, 0.366);
|
|
62
|
+
vec3 c5 = vec3(0.866, 0.301, 0.228);
|
|
63
|
+
vec3 c6 = vec3(0.976, 0.505, 0.096);
|
|
64
|
+
vec3 c7 = vec3(0.985, 0.768, 0.263);
|
|
65
|
+
vec3 c8 = vec3(0.988, 0.941, 0.729);
|
|
66
|
+
|
|
67
|
+
if (x < 0.125) return mix(c0, c1, x / 0.125);
|
|
68
|
+
if (x < 0.250) return mix(c1, c2, (x - 0.125) / 0.125);
|
|
69
|
+
if (x < 0.375) return mix(c2, c3, (x - 0.250) / 0.125);
|
|
70
|
+
if (x < 0.500) return mix(c3, c4, (x - 0.375) / 0.125);
|
|
71
|
+
if (x < 0.625) return mix(c4, c5, (x - 0.500) / 0.125);
|
|
72
|
+
if (x < 0.750) return mix(c5, c6, (x - 0.625) / 0.125);
|
|
73
|
+
if (x < 0.875) return mix(c6, c7, (x - 0.750) / 0.125);
|
|
74
|
+
return mix(c7, c8, (x - 0.875) / 0.125);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
vec3 heatmap_turbo(float x) {
|
|
78
|
+
x = clamp(x, 0.0, 1.0);
|
|
79
|
+
const vec4 kL = vec4(0.23, 0.11, 0.32, 1.0);
|
|
80
|
+
const vec4 kH = vec4(0.92, 0.95, 0.64, 1.0);
|
|
81
|
+
const vec3 g0 = vec3(0.12, 0.01, 0.22);
|
|
82
|
+
const vec3 g1 = vec3(0.13, 0.15, 0.48);
|
|
83
|
+
const vec3 g2 = vec3(0.15, 0.65, 0.51);
|
|
84
|
+
const vec3 g3 = vec3(0.85, 0.60, 0.12);
|
|
85
|
+
const vec3 g4 = vec3(0.92, 0.11, 0.43);
|
|
86
|
+
|
|
87
|
+
if (x < 0.25) return mix(g0, g1, x / 0.25);
|
|
88
|
+
if (x < 0.50) return mix(g1, g2, (x - 0.25) / 0.25);
|
|
89
|
+
if (x < 0.75) return mix(g2, g3, (x - 0.50) / 0.25);
|
|
90
|
+
return mix(g3, g4, (x - 0.75) / 0.25);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
vec3 heatmap_ink_fire(float x) {
|
|
94
|
+
x = clamp(x, 0.0, 1.0);
|
|
95
|
+
vec3 c0 = vec3(1.0, 1.0, 1.0); // White
|
|
96
|
+
vec3 c1 = vec3(1.0, 0.9, 0.2); // Yellow
|
|
97
|
+
vec3 c2 = vec3(1.0, 0.2, 0.1); // Red
|
|
98
|
+
vec3 c3 = vec3(0.4, 0.0, 0.0); // Dark Red
|
|
99
|
+
vec3 c4 = vec3(0.0, 0.0, 0.0); // Black
|
|
100
|
+
|
|
101
|
+
if (x < 0.25) return mix(c0, c1, x / 0.25);
|
|
102
|
+
if (x < 0.50) return mix(c1, c2, (x - 0.25) / 0.25);
|
|
103
|
+
if (x < 0.75) return mix(c2, c3, (x - 0.50) / 0.25);
|
|
104
|
+
return mix(c3, c4, (x - 0.75) / 0.25);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
vec3 heatmap_magma(float x) {
|
|
108
|
+
x = clamp(x, 0.0, 1.0);
|
|
109
|
+
vec3 c0 = vec3(0.001, 0.000, 0.031);
|
|
110
|
+
vec3 c1 = vec3(0.170, 0.047, 0.360);
|
|
111
|
+
vec3 c2 = vec3(0.447, 0.051, 0.439);
|
|
112
|
+
vec3 c3 = vec3(0.729, 0.160, 0.345);
|
|
113
|
+
vec3 c4 = vec3(0.960, 0.419, 0.231);
|
|
114
|
+
vec3 c5 = vec3(0.988, 0.768, 0.470);
|
|
115
|
+
vec3 c6 = vec3(0.988, 0.988, 0.823);
|
|
116
|
+
|
|
117
|
+
if (x < 0.16) return mix(c0, c1, x / 0.16);
|
|
118
|
+
if (x < 0.32) return mix(c1, c2, (x - 0.16) / 0.16);
|
|
119
|
+
if (x < 0.48) return mix(c2, c3, (x - 0.32) / 0.16);
|
|
120
|
+
if (x < 0.64) return mix(c3, c4, (x - 0.48) / 0.16);
|
|
121
|
+
if (x < 0.80) return mix(c4, c5, (x - 0.64) / 0.16);
|
|
122
|
+
return mix(c5, c6, (x - 0.80) / 0.20);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
vec3 heatmap_grayscale(float x) {
|
|
126
|
+
return vec3(clamp(x, 0.0, 1.0));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
vec3 apply_heatmap(int scheme, float x) {
|
|
130
|
+
if (scheme == 1) return heatmap_viridis_like(x);
|
|
131
|
+
if (scheme == 2) return heatmap_plasma_like(x);
|
|
132
|
+
if (scheme == 3) return heatmap_inferno(x);
|
|
133
|
+
if (scheme == 4) return heatmap_turbo(x);
|
|
134
|
+
if (scheme == 5) return heatmap_ink_fire(x);
|
|
135
|
+
if (scheme == 6) return heatmap_magma(x);
|
|
136
|
+
if (scheme == 7) return heatmap_grayscale(x);
|
|
137
|
+
return heatmap_classic(x);
|
|
138
|
+
}
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
DENSITY_SCHEMES = [
|
|
142
|
+
"Classic (B-W-C)",
|
|
143
|
+
"Viridis",
|
|
144
|
+
"Plasma",
|
|
145
|
+
"Inferno",
|
|
146
|
+
"Turbo (Rainbow)",
|
|
147
|
+
"Ink Fire (White BG)",
|
|
148
|
+
"Magma",
|
|
149
|
+
"Grayscale"
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
# ==============================================================================
|
|
153
|
+
# PASS 1: EXACT RENDERING (Primal Geometry)
|
|
154
|
+
# ==============================================================================
|
|
155
|
+
|
|
156
|
+
# --- LINES ---
|
|
157
|
+
|
|
158
|
+
EXACT_LINES_VS = r"""
|
|
159
|
+
#version 330 core
|
|
160
|
+
layout(location=0) in float a_t;
|
|
161
|
+
layout(location=1) in vec2 a_ab;
|
|
162
|
+
layout(location=2) in vec4 a_col;
|
|
163
|
+
|
|
164
|
+
uniform mat4 u_mvp;
|
|
165
|
+
uniform vec2 u_xrange;
|
|
166
|
+
uniform vec4 u_window;
|
|
167
|
+
uniform int u_use_color;
|
|
168
|
+
uniform float u_alpha;
|
|
169
|
+
uniform int u_enable_subsample;
|
|
170
|
+
uniform float u_keep_prob;
|
|
171
|
+
uniform int u_total_count;
|
|
172
|
+
uniform vec2 u_layer_offset;
|
|
173
|
+
|
|
174
|
+
out vec4 v_col;
|
|
175
|
+
flat out float v_id_norm;
|
|
176
|
+
|
|
177
|
+
void main() {
|
|
178
|
+
float x = mix(u_xrange.x, u_xrange.y, a_t);
|
|
179
|
+
float y = a_ab.x * x + a_ab.y;
|
|
180
|
+
vec2 w = vec2(x, y) + u_layer_offset;
|
|
181
|
+
|
|
182
|
+
gl_Position = u_mvp * vec4(w, 0.0, 1.0);
|
|
183
|
+
|
|
184
|
+
gl_ClipDistance[0] = w.x - u_window.x;
|
|
185
|
+
gl_ClipDistance[1] = u_window.y - w.x;
|
|
186
|
+
gl_ClipDistance[2] = w.y - u_window.z;
|
|
187
|
+
gl_ClipDistance[3] = u_window.w - w.y;
|
|
188
|
+
|
|
189
|
+
float l = u_window.x, r = u_window.y;
|
|
190
|
+
float xmin = u_xrange.x, xmax = u_xrange.y;
|
|
191
|
+
float xA = max(l, xmin);
|
|
192
|
+
float xB = min(r, xmax);
|
|
193
|
+
bool noOverlapX = (xA > xB);
|
|
194
|
+
float yA = a_ab.x * xA + a_ab.y;
|
|
195
|
+
float yB = a_ab.x * xB + a_ab.y;
|
|
196
|
+
float bottom = u_window.z, top = u_window.w;
|
|
197
|
+
bool outsideY = (yA > top && yB > top) || (yA < bottom && yB < bottom);
|
|
198
|
+
|
|
199
|
+
uint id = uint(gl_InstanceID);
|
|
200
|
+
v_id_norm = (u_total_count > 1) ? float(id) / float(u_total_count - 1) : 0.0;
|
|
201
|
+
|
|
202
|
+
id ^= id >> 17; id *= 0xed5ad4bbu; id ^= id >> 11;
|
|
203
|
+
id *= 0xac4c1b51u; id ^= id >> 15; id *= 0x31848babu;
|
|
204
|
+
float rnd = float(id & 0x00FFFFFFu) * (1.0/16777215.0);
|
|
205
|
+
bool drop = (u_enable_subsample == 1) && (rnd > u_keep_prob);
|
|
206
|
+
|
|
207
|
+
if (noOverlapX || outsideY || drop) {
|
|
208
|
+
gl_ClipDistance[0] = -1.0;
|
|
209
|
+
gl_ClipDistance[1] = -1.0;
|
|
210
|
+
gl_ClipDistance[2] = -1.0;
|
|
211
|
+
gl_ClipDistance[3] = -1.0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
v_col = (u_use_color == 1) ? a_col : vec4(0.0, 0.0, 0.0, 1.0);
|
|
215
|
+
v_col.a *= u_alpha;
|
|
216
|
+
}
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
WIDE_LINES_INSTANCED_VS = r"""
|
|
220
|
+
#version 330 core
|
|
221
|
+
|
|
222
|
+
layout(location=0) in vec2 a_corner; // (t, side): t in {0,1}, side in {-0.5,+0.5}
|
|
223
|
+
layout(location=1) in vec2 a_ab; // slope, intercept
|
|
224
|
+
layout(location=2) in vec4 a_col; // instanced color
|
|
225
|
+
|
|
226
|
+
uniform vec2 u_xrange;
|
|
227
|
+
uniform vec4 u_window; // l, r, b, t
|
|
228
|
+
uniform vec2 u_ndc_scale;
|
|
229
|
+
uniform vec2 u_ndc_offset;
|
|
230
|
+
uniform vec2 u_viewport_size;
|
|
231
|
+
uniform float u_width;
|
|
232
|
+
uniform float u_alpha;
|
|
233
|
+
uniform int u_use_color;
|
|
234
|
+
uniform float u_keep_prob;
|
|
235
|
+
uniform int u_total_count;
|
|
236
|
+
uniform vec2 u_layer_offset;
|
|
237
|
+
|
|
238
|
+
out vec4 v_col;
|
|
239
|
+
flat out float v_id_norm;
|
|
240
|
+
|
|
241
|
+
void main() {
|
|
242
|
+
uint id = uint(gl_InstanceID);
|
|
243
|
+
v_id_norm = (u_total_count > 1) ? float(id) / float(u_total_count - 1) : 0.0;
|
|
244
|
+
|
|
245
|
+
// Early probabilistic LOD
|
|
246
|
+
uint h = id;
|
|
247
|
+
h ^= h >> 17; h *= 0xed5ad4bbu; h ^= h >> 11;
|
|
248
|
+
h *= 0xac4c1b51u; h ^= h >> 15; h *= 0x31848babu;
|
|
249
|
+
float rnd = float(h & 0x00FFFFFFu) * (1.0 / 16777215.0);
|
|
250
|
+
bool drop = rnd > u_keep_prob;
|
|
251
|
+
|
|
252
|
+
float l = u_window.x;
|
|
253
|
+
float r = u_window.y;
|
|
254
|
+
float b = u_window.z;
|
|
255
|
+
float t = u_window.w;
|
|
256
|
+
|
|
257
|
+
float xmin = u_xrange.x;
|
|
258
|
+
float xmax = u_xrange.y;
|
|
259
|
+
|
|
260
|
+
float xA = max(l, xmin);
|
|
261
|
+
float xB = min(r, xmax);
|
|
262
|
+
bool noOverlapX = (xA > xB);
|
|
263
|
+
|
|
264
|
+
float yA = a_ab.x * xA + a_ab.y;
|
|
265
|
+
float yB = a_ab.x * xB + a_ab.y;
|
|
266
|
+
bool outsideY = (yA > t && yB > t) || (yA < b && yB < b);
|
|
267
|
+
|
|
268
|
+
if (drop || noOverlapX || outsideY) {
|
|
269
|
+
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
270
|
+
v_col = vec4(0.0);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
float x0 = xmin;
|
|
275
|
+
float x1 = xmax;
|
|
276
|
+
float y0 = a_ab.x * x0 + a_ab.y;
|
|
277
|
+
float y1 = a_ab.x * x1 + a_ab.y;
|
|
278
|
+
|
|
279
|
+
vec2 ndc0 = (vec2(x0, y0) + u_layer_offset) * u_ndc_scale + u_ndc_offset;
|
|
280
|
+
vec2 ndc1 = (vec2(x1, y1) + u_layer_offset) * u_ndc_scale + u_ndc_offset;
|
|
281
|
+
|
|
282
|
+
vec2 dir_px = (ndc1 - ndc0) * (0.5 * u_viewport_size);
|
|
283
|
+
float len2 = dot(dir_px, dir_px);
|
|
284
|
+
|
|
285
|
+
vec2 n_px = (len2 > 1e-12)
|
|
286
|
+
? normalize(vec2(-dir_px.y, dir_px.x))
|
|
287
|
+
: vec2(0.0, 1.0);
|
|
288
|
+
|
|
289
|
+
vec2 p_ndc = mix(ndc0, ndc1, a_corner.x);
|
|
290
|
+
p_ndc += n_px * ((u_width / u_viewport_size) * a_corner.y);
|
|
291
|
+
|
|
292
|
+
gl_Position = vec4(p_ndc, 0.0, 1.0);
|
|
293
|
+
|
|
294
|
+
v_col = (u_use_color == 1) ? a_col : vec4(0.0, 0.0, 0.0, 1.0);
|
|
295
|
+
v_col.a *= u_alpha;
|
|
296
|
+
}
|
|
297
|
+
"""
|
|
298
|
+
|
|
299
|
+
EXACT_LINES_FS = r"""
|
|
300
|
+
#version 330 core
|
|
301
|
+
in vec4 v_col;
|
|
302
|
+
flat in float v_id_norm;
|
|
303
|
+
out vec4 FragColor;
|
|
304
|
+
|
|
305
|
+
uniform int u_use_colormap;
|
|
306
|
+
uniform int u_scheme;
|
|
307
|
+
|
|
308
|
+
""" + HEATMAP_FUNCS + r"""
|
|
309
|
+
|
|
310
|
+
void main() {
|
|
311
|
+
vec4 color = v_col;
|
|
312
|
+
if (u_use_colormap == 1) {
|
|
313
|
+
color.rgb = apply_heatmap(u_scheme, v_id_norm);
|
|
314
|
+
}
|
|
315
|
+
FragColor = color;
|
|
316
|
+
}
|
|
317
|
+
"""
|
|
318
|
+
|
|
319
|
+
# --- SCATTERS ---
|
|
320
|
+
|
|
321
|
+
SCATTER_VS = r"""
|
|
322
|
+
#version 330 core
|
|
323
|
+
layout(location=0) in vec2 a_pos;
|
|
324
|
+
layout(location=1) in vec4 a_color;
|
|
325
|
+
uniform mat4 u_mvp;
|
|
326
|
+
uniform float u_size;
|
|
327
|
+
uniform float u_alpha;
|
|
328
|
+
uniform vec2 u_layer_offset;
|
|
329
|
+
out vec4 v_col;
|
|
330
|
+
void main() {
|
|
331
|
+
gl_Position = u_mvp * vec4(a_pos + u_layer_offset, 0.0, 1.0);
|
|
332
|
+
gl_PointSize = u_size;
|
|
333
|
+
v_col = a_color;
|
|
334
|
+
v_col.a *= u_alpha;
|
|
335
|
+
}
|
|
336
|
+
"""
|
|
337
|
+
|
|
338
|
+
SCATTER_FS = r"""
|
|
339
|
+
#version 330 core
|
|
340
|
+
in vec4 v_col;
|
|
341
|
+
out vec4 FragColor;
|
|
342
|
+
|
|
343
|
+
uniform int u_outline_enabled;
|
|
344
|
+
uniform vec4 u_outline_color;
|
|
345
|
+
uniform float u_outline_width_px;
|
|
346
|
+
uniform float u_point_size_px;
|
|
347
|
+
|
|
348
|
+
void main() {
|
|
349
|
+
vec2 p = gl_PointCoord - vec2(0.5);
|
|
350
|
+
float r = length(p) * 2.0; // 0 center, ~1 edge
|
|
351
|
+
|
|
352
|
+
if (r > 1.0) discard;
|
|
353
|
+
|
|
354
|
+
float outline_frac = (u_point_size_px > 0.0)
|
|
355
|
+
? clamp(u_outline_width_px / u_point_size_px, 0.0, 0.49)
|
|
356
|
+
: 0.0;
|
|
357
|
+
|
|
358
|
+
float fill_radius = 1.0 - 2.0 * outline_frac;
|
|
359
|
+
|
|
360
|
+
vec4 col = v_col;
|
|
361
|
+
|
|
362
|
+
if (u_outline_enabled == 1 && r > fill_radius) {
|
|
363
|
+
col.rgb = u_outline_color.rgb;
|
|
364
|
+
col.a *= u_outline_color.a;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Soft edge antialiasing
|
|
368
|
+
float feather = fwidth(r) * 1.5;
|
|
369
|
+
col.a *= 1.0 - smoothstep(1.0 - feather, 1.0, r);
|
|
370
|
+
|
|
371
|
+
FragColor = col;
|
|
372
|
+
}
|
|
373
|
+
"""
|
|
374
|
+
|
|
375
|
+
# --- STRIPS ---
|
|
376
|
+
|
|
377
|
+
STRIP_VS = r"""
|
|
378
|
+
#version 330 core
|
|
379
|
+
layout(location=0) in vec2 a_pos;
|
|
380
|
+
uniform mat4 u_mvp;
|
|
381
|
+
uniform vec4 u_color;
|
|
382
|
+
uniform float u_alpha;
|
|
383
|
+
uniform vec2 u_layer_offset;
|
|
384
|
+
out vec4 v_col;
|
|
385
|
+
void main() {
|
|
386
|
+
gl_Position = u_mvp * vec4(a_pos + u_layer_offset, 0.0, 1.0);
|
|
387
|
+
v_col = u_color;
|
|
388
|
+
v_col.a *= u_alpha;
|
|
389
|
+
}
|
|
390
|
+
"""
|
|
391
|
+
|
|
392
|
+
STRIP_FS = r"""
|
|
393
|
+
#version 330 core
|
|
394
|
+
in vec4 v_col;
|
|
395
|
+
out vec4 FragColor;
|
|
396
|
+
void main() {
|
|
397
|
+
FragColor = v_col;
|
|
398
|
+
}
|
|
399
|
+
"""
|
|
400
|
+
|
|
401
|
+
# --- WIDE LINES (Quad Expansion) ---
|
|
402
|
+
|
|
403
|
+
WIDE_LINE_VS = r"""
|
|
404
|
+
#version 330 core
|
|
405
|
+
layout(location=0) in vec2 a_pos;
|
|
406
|
+
layout(location=1) in vec2 a_next;
|
|
407
|
+
layout(location=2) in float a_side; // -1.0 or 1.0
|
|
408
|
+
|
|
409
|
+
uniform mat4 u_mvp;
|
|
410
|
+
uniform vec2 u_viewport_size;
|
|
411
|
+
uniform float u_width;
|
|
412
|
+
uniform vec4 u_color;
|
|
413
|
+
uniform float u_alpha;
|
|
414
|
+
|
|
415
|
+
out vec4 v_col;
|
|
416
|
+
|
|
417
|
+
void main() {
|
|
418
|
+
float width = max(1.0, u_width);
|
|
419
|
+
|
|
420
|
+
vec4 p1 = u_mvp * vec4(a_pos, 0.0, 1.0);
|
|
421
|
+
vec4 p2 = u_mvp * vec4(a_next, 0.0, 1.0);
|
|
422
|
+
|
|
423
|
+
vec2 ndc1 = p1.xy / p1.w;
|
|
424
|
+
vec2 ndc2 = p2.xy / p2.w;
|
|
425
|
+
|
|
426
|
+
// Direction and normal in screen space
|
|
427
|
+
vec2 dir = normalize((ndc2 - ndc1) * u_viewport_size);
|
|
428
|
+
vec2 norm = vec2(-dir.y, dir.x);
|
|
429
|
+
|
|
430
|
+
// Offset in NDC space
|
|
431
|
+
vec2 offset = norm * (width / u_viewport_size) * a_side;
|
|
432
|
+
|
|
433
|
+
// Determine if this vertex belongs to the start or end of the segment
|
|
434
|
+
// We assume 4 vertices per segment (0,1 at start; 2,3 at end)
|
|
435
|
+
float is_end = float(gl_VertexID % 4 >= 2);
|
|
436
|
+
vec4 p = mix(p1, p2, is_end);
|
|
437
|
+
|
|
438
|
+
p.xy += offset * p.w;
|
|
439
|
+
|
|
440
|
+
gl_Position = p;
|
|
441
|
+
v_col = u_color;
|
|
442
|
+
v_col.a *= u_alpha;
|
|
443
|
+
}
|
|
444
|
+
"""
|
|
445
|
+
|
|
446
|
+
WIDE_LINE_FS = r"""
|
|
447
|
+
#version 330 core
|
|
448
|
+
in vec4 v_col;
|
|
449
|
+
out vec4 FragColor;
|
|
450
|
+
void main() {
|
|
451
|
+
FragColor = v_col;
|
|
452
|
+
}
|
|
453
|
+
"""
|
|
454
|
+
|
|
455
|
+
# --- INSTANCED SEGMENTS (GPU Expansion) ---
|
|
456
|
+
|
|
457
|
+
WIDE_SEGMENT_INSTANCED_VS = r"""
|
|
458
|
+
#version 330 core
|
|
459
|
+
|
|
460
|
+
layout(location=0) in vec2 a_corner; // (t, side): t in {0,1}, side in {-0.5,+0.5}
|
|
461
|
+
layout(location=1) in vec2 i_p0; // segment start
|
|
462
|
+
layout(location=2) in vec2 i_p1; // segment end
|
|
463
|
+
|
|
464
|
+
uniform vec2 u_ndc_scale; // ( 2/(r-l), 2/(t-b) )
|
|
465
|
+
uniform vec2 u_ndc_offset; // (-(r+l)/(r-l), -(t+b)/(t-b))
|
|
466
|
+
uniform vec2 u_viewport_size; // framebuffer size in pixels
|
|
467
|
+
uniform vec4 u_color;
|
|
468
|
+
uniform float u_alpha;
|
|
469
|
+
uniform float u_width;
|
|
470
|
+
uniform float u_id_norm;
|
|
471
|
+
uniform vec2 u_layer_offset;
|
|
472
|
+
|
|
473
|
+
out vec4 v_col;
|
|
474
|
+
flat out float v_id_norm;
|
|
475
|
+
|
|
476
|
+
void main() {
|
|
477
|
+
vec2 ndc0 = (i_p0 + u_layer_offset) * u_ndc_scale + u_ndc_offset;
|
|
478
|
+
vec2 ndc1 = (i_p1 + u_layer_offset) * u_ndc_scale + u_ndc_offset;
|
|
479
|
+
|
|
480
|
+
// Convert NDC delta to pixels
|
|
481
|
+
vec2 dir_px = (ndc1 - ndc0) * (0.5 * u_viewport_size);
|
|
482
|
+
float len2 = dot(dir_px, dir_px);
|
|
483
|
+
|
|
484
|
+
vec2 n_px = (len2 > 1e-12)
|
|
485
|
+
? normalize(vec2(-dir_px.y, dir_px.x))
|
|
486
|
+
: vec2(0.0, 1.0);
|
|
487
|
+
|
|
488
|
+
vec2 p_ndc = mix(ndc0, ndc1, a_corner.x);
|
|
489
|
+
|
|
490
|
+
// u_width is full width; offset from centerline is ±0.5*u_width
|
|
491
|
+
vec2 offset_ndc = n_px * (u_width / u_viewport_size) * a_corner.y;
|
|
492
|
+
p_ndc += offset_ndc;
|
|
493
|
+
|
|
494
|
+
gl_Position = vec4(p_ndc, 0.0, 1.0);
|
|
495
|
+
|
|
496
|
+
v_col = u_color;
|
|
497
|
+
v_col.a *= u_alpha;
|
|
498
|
+
v_id_norm = u_id_norm;
|
|
499
|
+
}
|
|
500
|
+
"""
|
|
501
|
+
|
|
502
|
+
WIDE_SEGMENT_INSTANCED_FS = r"""
|
|
503
|
+
#version 330 core
|
|
504
|
+
in vec4 v_col;
|
|
505
|
+
flat in float v_id_norm;
|
|
506
|
+
out vec4 FragColor;
|
|
507
|
+
|
|
508
|
+
uniform int u_use_colormap;
|
|
509
|
+
uniform int u_scheme;
|
|
510
|
+
|
|
511
|
+
""" + HEATMAP_FUNCS + r"""
|
|
512
|
+
|
|
513
|
+
void main() {
|
|
514
|
+
vec4 color = v_col;
|
|
515
|
+
if (u_use_colormap == 1) {
|
|
516
|
+
color.rgb = apply_heatmap(u_scheme, v_id_norm);
|
|
517
|
+
}
|
|
518
|
+
FragColor = color;
|
|
519
|
+
}
|
|
520
|
+
"""
|
|
521
|
+
|
|
522
|
+
WIDE_SEGMENT_DENSITY_FS = r"""
|
|
523
|
+
#version 330 core
|
|
524
|
+
in vec4 v_col;
|
|
525
|
+
layout(location=0) out float FragValue;
|
|
526
|
+
|
|
527
|
+
uniform int u_density_weighted;
|
|
528
|
+
|
|
529
|
+
void main() {
|
|
530
|
+
FragValue = (u_density_weighted == 1) ? v_col.a : 1.0;
|
|
531
|
+
}
|
|
532
|
+
"""
|
|
533
|
+
|
|
534
|
+
# --- PATCHES ---
|
|
535
|
+
|
|
536
|
+
PATCH_VS = r"""
|
|
537
|
+
#version 330 core
|
|
538
|
+
layout(location=0) in vec2 a_pos;
|
|
539
|
+
uniform mat4 u_mvp;
|
|
540
|
+
uniform vec4 u_color;
|
|
541
|
+
uniform float u_alpha;
|
|
542
|
+
uniform vec2 u_layer_offset;
|
|
543
|
+
out vec4 v_col;
|
|
544
|
+
void main() {
|
|
545
|
+
gl_Position = u_mvp * vec4(a_pos + u_layer_offset, 0.0, 1.0);
|
|
546
|
+
v_col = u_color;
|
|
547
|
+
v_col.a *= u_alpha;
|
|
548
|
+
}
|
|
549
|
+
"""
|
|
550
|
+
|
|
551
|
+
PATCH_FS = r"""
|
|
552
|
+
#version 330 core
|
|
553
|
+
in vec4 v_col;
|
|
554
|
+
out vec4 FragColor;
|
|
555
|
+
void main() {
|
|
556
|
+
FragColor = v_col;
|
|
557
|
+
}
|
|
558
|
+
"""
|
|
559
|
+
|
|
560
|
+
# ==============================================================================
|
|
561
|
+
# PASS 2: DENSITY ACCUMULATION
|
|
562
|
+
# ==============================================================================
|
|
563
|
+
|
|
564
|
+
DENSITY_ACCUM_FS = r"""
|
|
565
|
+
#version 330 core
|
|
566
|
+
in vec4 v_col;
|
|
567
|
+
layout(location=0) out float FragValue;
|
|
568
|
+
|
|
569
|
+
uniform int u_density_weighted;
|
|
570
|
+
|
|
571
|
+
void main() {
|
|
572
|
+
FragValue = (u_density_weighted == 1) ? v_col.a : 1.0;
|
|
573
|
+
}
|
|
574
|
+
"""
|
|
575
|
+
|
|
576
|
+
DENSITY_POINTS_VS = r"""
|
|
577
|
+
#version 330 core
|
|
578
|
+
layout(location=0) in vec2 a_pos;
|
|
579
|
+
layout(location=1) in vec4 a_col;
|
|
580
|
+
uniform mat4 u_mvp;
|
|
581
|
+
uniform float u_size;
|
|
582
|
+
uniform float u_alpha;
|
|
583
|
+
uniform vec2 u_layer_offset;
|
|
584
|
+
out float v_alpha;
|
|
585
|
+
void main() {
|
|
586
|
+
gl_Position = u_mvp * vec4(a_pos + u_layer_offset, 0.0, 1.0);
|
|
587
|
+
gl_PointSize = u_size;
|
|
588
|
+
v_alpha = a_col.a * u_alpha;
|
|
589
|
+
}
|
|
590
|
+
"""
|
|
591
|
+
|
|
592
|
+
DENSITY_POINTS_FS = r"""
|
|
593
|
+
#version 330 core
|
|
594
|
+
in float v_alpha;
|
|
595
|
+
layout(location=0) out float FragValue;
|
|
596
|
+
void main() {
|
|
597
|
+
vec2 coord = gl_PointCoord - vec2(0.5);
|
|
598
|
+
if (dot(coord, coord) > 0.25) discard;
|
|
599
|
+
FragValue = v_alpha;
|
|
600
|
+
}
|
|
601
|
+
"""
|
|
602
|
+
|
|
603
|
+
DENSITY_RESOLVE_FS = r"""
|
|
604
|
+
#version 330 core
|
|
605
|
+
#define log10(x) (log(x) / log(10.0))
|
|
606
|
+
|
|
607
|
+
in vec2 v_uv;
|
|
608
|
+
out vec4 FragColor;
|
|
609
|
+
|
|
610
|
+
uniform sampler2D u_tex;
|
|
611
|
+
uniform float u_gain;
|
|
612
|
+
uniform float u_log_scale;
|
|
613
|
+
uniform int u_scheme;
|
|
614
|
+
|
|
615
|
+
""" + HEATMAP_FUNCS + r"""
|
|
616
|
+
|
|
617
|
+
void main() {
|
|
618
|
+
float val = texture(u_tex, v_uv).r;
|
|
619
|
+
if (val <= 0.0) discard;
|
|
620
|
+
|
|
621
|
+
// Normalize log value
|
|
622
|
+
float norm = clamp(log10(1.0 + val * u_gain) / u_log_scale, 0.0, 1.0);
|
|
623
|
+
FragColor = vec4(apply_heatmap(u_scheme, norm), 1.0);
|
|
624
|
+
}
|
|
625
|
+
"""
|
|
626
|
+
|
|
627
|
+
# ==============================================================================
|
|
628
|
+
# PASS 3: PICKING & INTERACTION
|
|
629
|
+
# ==============================================================================
|
|
630
|
+
|
|
631
|
+
PICKING_LINES_VS = r"""
|
|
632
|
+
#version 330 core
|
|
633
|
+
layout(location=0) in float a_t;
|
|
634
|
+
layout(location=1) in vec2 a_ab;
|
|
635
|
+
|
|
636
|
+
uniform mat4 u_mvp;
|
|
637
|
+
uniform vec2 u_xrange;
|
|
638
|
+
uniform vec4 u_window;
|
|
639
|
+
uniform vec2 u_layer_offset;
|
|
640
|
+
uniform int u_id_offset;
|
|
641
|
+
|
|
642
|
+
flat out int v_id;
|
|
643
|
+
|
|
644
|
+
void main() {
|
|
645
|
+
float x = mix(u_xrange.x, u_xrange.y, a_t);
|
|
646
|
+
float y = a_ab.x * x + a_ab.y;
|
|
647
|
+
vec2 w = vec2(x, y) + u_layer_offset;
|
|
648
|
+
|
|
649
|
+
gl_Position = u_mvp * vec4(w, 0.0, 1.0);
|
|
650
|
+
|
|
651
|
+
gl_ClipDistance[0] = w.x - u_window.x;
|
|
652
|
+
gl_ClipDistance[1] = u_window.y - w.x;
|
|
653
|
+
gl_ClipDistance[2] = w.y - u_window.z;
|
|
654
|
+
gl_ClipDistance[3] = u_window.w - w.y;
|
|
655
|
+
|
|
656
|
+
v_id = u_id_offset + gl_InstanceID + 1;
|
|
657
|
+
}
|
|
658
|
+
"""
|
|
659
|
+
|
|
660
|
+
PICKING_LINES_FS = r"""
|
|
661
|
+
#version 330 core
|
|
662
|
+
flat in int v_id;
|
|
663
|
+
layout(location=0) out int FragID;
|
|
664
|
+
void main() {
|
|
665
|
+
FragID = v_id;
|
|
666
|
+
}
|
|
667
|
+
"""
|
|
668
|
+
|
|
669
|
+
PICKING_SCATTER_VS = r"""
|
|
670
|
+
#version 330 core
|
|
671
|
+
layout(location=0) in vec2 a_pos;
|
|
672
|
+
|
|
673
|
+
uniform mat4 u_mvp;
|
|
674
|
+
uniform float u_size;
|
|
675
|
+
uniform int u_id_offset;
|
|
676
|
+
uniform vec2 u_layer_offset;
|
|
677
|
+
|
|
678
|
+
flat out int v_id;
|
|
679
|
+
|
|
680
|
+
void main() {
|
|
681
|
+
gl_Position = u_mvp * vec4(a_pos + u_layer_offset, 0.0, 1.0);
|
|
682
|
+
gl_PointSize = u_size;
|
|
683
|
+
v_id = u_id_offset + gl_VertexID + 1;
|
|
684
|
+
}
|
|
685
|
+
"""
|
|
686
|
+
|
|
687
|
+
PICKING_SCATTER_FS = r"""
|
|
688
|
+
#version 330 core
|
|
689
|
+
flat in int v_id;
|
|
690
|
+
layout(location=0) out int FragID;
|
|
691
|
+
|
|
692
|
+
void main() {
|
|
693
|
+
vec2 coord = gl_PointCoord - vec2(0.5);
|
|
694
|
+
if (dot(coord, coord) > 0.25) discard;
|
|
695
|
+
FragID = v_id;
|
|
696
|
+
}
|
|
697
|
+
"""
|
|
698
|
+
|
|
699
|
+
PICKING_STRIP_VS = r"""
|
|
700
|
+
#version 330 core
|
|
701
|
+
layout(location=0) in vec2 a_pos;
|
|
702
|
+
|
|
703
|
+
uniform mat4 u_mvp;
|
|
704
|
+
uniform int u_id;
|
|
705
|
+
uniform vec2 u_layer_offset;
|
|
706
|
+
|
|
707
|
+
flat out int v_id;
|
|
708
|
+
|
|
709
|
+
void main() {
|
|
710
|
+
gl_Position = u_mvp * vec4(a_pos + u_layer_offset, 0.0, 1.0);
|
|
711
|
+
v_id = u_id;
|
|
712
|
+
}
|
|
713
|
+
"""
|
|
714
|
+
|
|
715
|
+
PICKING_STRIP_FS = r"""
|
|
716
|
+
#version 330 core
|
|
717
|
+
flat in int v_id;
|
|
718
|
+
layout(location=0) out int FragID;
|
|
719
|
+
void main() {
|
|
720
|
+
FragID = v_id;
|
|
721
|
+
}
|
|
722
|
+
"""
|
|
723
|
+
|
|
724
|
+
PICKING_PATCH_VS = r"""
|
|
725
|
+
#version 330 core
|
|
726
|
+
layout(location=0) in vec2 a_pos;
|
|
727
|
+
uniform mat4 u_mvp;
|
|
728
|
+
uniform int u_id;
|
|
729
|
+
uniform vec2 u_layer_offset;
|
|
730
|
+
flat out int v_id;
|
|
731
|
+
void main() {
|
|
732
|
+
gl_Position = u_mvp * vec4(a_pos + u_layer_offset, 0.0, 1.0);
|
|
733
|
+
v_id = u_id;
|
|
734
|
+
}
|
|
735
|
+
"""
|
|
736
|
+
|
|
737
|
+
PICKING_PATCH_FS = r"""
|
|
738
|
+
#version 330 core
|
|
739
|
+
flat in int v_id;
|
|
740
|
+
layout(location=0) out int FragID;
|
|
741
|
+
void main() {
|
|
742
|
+
FragID = v_id;
|
|
743
|
+
}
|
|
744
|
+
"""
|
|
745
|
+
|
|
746
|
+
INTERACTION_FULLSCREEN_VS = r"""
|
|
747
|
+
#version 330 core
|
|
748
|
+
out vec2 v_uv;
|
|
749
|
+
const vec2 verts[4] = vec2[4](
|
|
750
|
+
vec2(-1.0, -1.0), vec2( 1.0, -1.0),
|
|
751
|
+
vec2(-1.0, 1.0), vec2( 1.0, 1.0)
|
|
752
|
+
);
|
|
753
|
+
void main() {
|
|
754
|
+
gl_Position = vec4(verts[gl_VertexID], 0.0, 1.0);
|
|
755
|
+
v_uv = verts[gl_VertexID] * 0.5 + 0.5;
|
|
756
|
+
}
|
|
757
|
+
"""
|
|
758
|
+
|
|
759
|
+
CACHE_IMPOSTOR_FS = r"""
|
|
760
|
+
#version 330 core
|
|
761
|
+
in vec2 v_uv;
|
|
762
|
+
out vec4 FragColor;
|
|
763
|
+
|
|
764
|
+
uniform sampler2D u_tex;
|
|
765
|
+
uniform vec4 u_cache_window;
|
|
766
|
+
uniform vec4 u_cur_window;
|
|
767
|
+
|
|
768
|
+
void main() {
|
|
769
|
+
float wx = mix(u_cur_window.x, u_cur_window.y, v_uv.x);
|
|
770
|
+
float wy = mix(u_cur_window.z, u_cur_window.w, v_uv.y);
|
|
771
|
+
|
|
772
|
+
float cache_u = (wx - u_cache_window.x) / (u_cache_window.y - u_cache_window.x);
|
|
773
|
+
float cache_v = (wy - u_cache_window.z) / (u_cache_window.w - u_cache_window.z);
|
|
774
|
+
|
|
775
|
+
cache_u = clamp(cache_u, 0.0, 1.0);
|
|
776
|
+
cache_v = clamp(cache_v, 0.0, 1.0);
|
|
777
|
+
FragColor = texture(u_tex, vec2(cache_u, cache_v));
|
|
778
|
+
}
|
|
779
|
+
"""
|
|
780
|
+
|
|
781
|
+
# ==============================================================================
|
|
782
|
+
# PASS 4: POST-PROCESSING
|
|
783
|
+
# ==============================================================================
|
|
784
|
+
|
|
785
|
+
POST_FX_VS = r"""
|
|
786
|
+
#version 330 core
|
|
787
|
+
out vec2 v_uv;
|
|
788
|
+
|
|
789
|
+
const vec2 verts[4] = vec2[4](
|
|
790
|
+
vec2(-1.0, -1.0),
|
|
791
|
+
vec2( 1.0, -1.0),
|
|
792
|
+
vec2(-1.0, 1.0),
|
|
793
|
+
vec2( 1.0, 1.0)
|
|
794
|
+
);
|
|
795
|
+
|
|
796
|
+
void main() {
|
|
797
|
+
vec2 p = verts[gl_VertexID];
|
|
798
|
+
v_uv = p * 0.5 + 0.5;
|
|
799
|
+
gl_Position = vec4(p, 0.0, 1.0);
|
|
800
|
+
}
|
|
801
|
+
"""
|
|
802
|
+
|
|
803
|
+
GRADIENT_BG_FS = r"""
|
|
804
|
+
#version 330 core
|
|
805
|
+
in vec2 v_uv;
|
|
806
|
+
uniform vec3 u_top_color;
|
|
807
|
+
uniform vec3 u_bottom_color;
|
|
808
|
+
layout(location=0) out vec4 FragColor;
|
|
809
|
+
|
|
810
|
+
void main() {
|
|
811
|
+
FragColor = vec4(mix(u_bottom_color, u_top_color, v_uv.y), 1.0);
|
|
812
|
+
}
|
|
813
|
+
"""
|
|
814
|
+
|
|
815
|
+
BLOOM_EXTRACT_FS = r"""
|
|
816
|
+
#version 330 core
|
|
817
|
+
in vec2 v_uv;
|
|
818
|
+
uniform sampler2D u_tex;
|
|
819
|
+
uniform float u_threshold;
|
|
820
|
+
layout(location=0) out vec4 FragColor;
|
|
821
|
+
|
|
822
|
+
void main() {
|
|
823
|
+
vec4 color = texture(u_tex, v_uv);
|
|
824
|
+
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
|
825
|
+
if (brightness > u_threshold) {
|
|
826
|
+
FragColor = color;
|
|
827
|
+
} else {
|
|
828
|
+
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
"""
|
|
832
|
+
|
|
833
|
+
GAUSSIAN_BLUR_FS = r"""
|
|
834
|
+
#version 330 core
|
|
835
|
+
in vec2 v_uv;
|
|
836
|
+
uniform sampler2D u_tex;
|
|
837
|
+
uniform int u_horizontal;
|
|
838
|
+
uniform float u_radius;
|
|
839
|
+
layout(location=0) out vec4 FragColor;
|
|
840
|
+
|
|
841
|
+
void main() {
|
|
842
|
+
float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
|
|
843
|
+
vec2 tex_offset = 1.0 / textureSize(u_tex, 0);
|
|
844
|
+
vec3 result = texture(u_tex, v_uv).rgb * weight[0];
|
|
845
|
+
|
|
846
|
+
if(u_horizontal == 1) {
|
|
847
|
+
for(int i = 1; i < 5; ++i) {
|
|
848
|
+
result += texture(u_tex, v_uv + vec2(tex_offset.x * float(i) * u_radius, 0.0)).rgb * weight[i];
|
|
849
|
+
result += texture(u_tex, v_uv - vec2(tex_offset.x * float(i) * u_radius, 0.0)).rgb * weight[i];
|
|
850
|
+
}
|
|
851
|
+
} else {
|
|
852
|
+
for(int i = 1; i < 5; ++i) {
|
|
853
|
+
result += texture(u_tex, v_uv + vec2(0.0, tex_offset.y * float(i) * u_radius)).rgb * weight[i];
|
|
854
|
+
result += texture(u_tex, v_uv - vec2(0.0, tex_offset.y * float(i) * u_radius)).rgb * weight[i];
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
FragColor = vec4(result, 1.0);
|
|
858
|
+
}
|
|
859
|
+
"""
|
|
860
|
+
|
|
861
|
+
POST_COMPOSITE_FS = r"""
|
|
862
|
+
#version 330 core
|
|
863
|
+
in vec2 v_uv;
|
|
864
|
+
uniform sampler2D u_scene_tex;
|
|
865
|
+
uniform sampler2D u_bloom_tex;
|
|
866
|
+
|
|
867
|
+
uniform int u_bloom_enabled;
|
|
868
|
+
uniform float u_bloom_intensity;
|
|
869
|
+
|
|
870
|
+
layout(location=0) out vec4 FragColor;
|
|
871
|
+
|
|
872
|
+
void main() {
|
|
873
|
+
vec3 hdr_scene = texture(u_scene_tex, v_uv).rgb;
|
|
874
|
+
vec3 bloom = vec3(0.0);
|
|
875
|
+
|
|
876
|
+
if (u_bloom_enabled == 1) {
|
|
877
|
+
bloom = texture(u_bloom_tex, v_uv).rgb * u_bloom_intensity;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
vec3 color = hdr_scene + bloom;
|
|
881
|
+
|
|
882
|
+
// HDR Tone mapping if bloom is present
|
|
883
|
+
if (u_bloom_enabled == 1) {
|
|
884
|
+
color = color / (color + vec3(1.0));
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
FragColor = vec4(color, 1.0);
|
|
888
|
+
}
|
|
889
|
+
"""
|