makepad_draw/shader/
std.rs

1pub use {
2    crate::{
3        makepad_derive_live::*,
4        makepad_platform::*,
5        //live_traits::*,
6    }
7};
8
9live_design!{
10    link shaders;
11    
12    pub PI = 3.141592653589793
13    pub E = 2.718281828459045
14    pub LN2 = 0.6931471805599453
15    pub LN10 = 2.302585092994046
16    pub LOG2E = 1.4426950408889634
17    pub LOG10E = 0.4342944819032518
18    pub SQRT1_2 = 0.70710678118654757
19    pub TORAD = 0.017453292519943295
20    pub GOLDEN = 1.618033988749895
21    
22    pub GaussShadow = {
23        // ported from https://madebyevan.com/shaders/fast-rounded-rectangle-shadows/
24        // License: CC0 (http://creativecommons.org/publicdomain/zero/1.0/)
25        fn gaussian(x:float, sigma:float )->float{
26            let pi = 3.141592653589793;
27            return exp(-(x * x) / (2.0 * sigma * sigma)) / (sqrt(2.0 * pi) * sigma);
28        }
29                    
30        // This approximates the error function, needed for the gaussian integral
31        fn erf_vec2(x0:vec2)->vec2 {
32            let s = sign(x0);
33            let a = abs(x0);
34            let x1 = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;
35            x1 *= x1;
36            return s - s / (x1 * x1);
37        }
38        
39        fn erf_vec4(x0:vec4)->vec4 {
40            let s = sign(x0);
41            let a = abs(x0);
42            let x1 = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;
43            x1 *= x1;
44            return s - s / (x1 * x1);
45        }
46                    
47        // Return the blurred mask along the x dimension
48        fn rounded_box_shadow_x(x:float, y:float, sigma:float, corner:float, half_size:vec2)->float{
49            let delta = min(half_size.y - corner - abs(y), 0.0);
50            let curved = half_size.x - corner + sqrt(max(0.0, corner * corner - delta * delta));
51            let integral = 0.5 + 0.5 * erf_vec2((x + vec2(-curved, curved)) * (sqrt(0.5) / sigma));
52            return integral.y - integral.x;
53        }
54                    
55        // Return the mask for the shadow of a box from lower to upper
56        fn rounded_box_shadow(lower:vec2, upper:vec2, point:vec2, sigma:float, corner:float)->float{
57            // Center everything to make the math easier
58            let center = (lower + upper) * 0.5;
59            let half_size = (upper - lower) * 0.5;
60            point -= center;
61                            
62            // The signal is only non-zero in a limited range, so don't waste samples
63            let low = point.y - half_size.y;
64            let high = point.y + half_size.y;
65            let start = clamp(-3.0 * sigma, low, high);
66            let end = clamp(3.0 * sigma, low, high);
67                            
68            // Accumulate samples (we can get away with surprisingly few samples)
69            let step = (end - start) / 4.0;
70            let y = start + step * 0.5;
71            let value = 0.0;
72            for i in 0..4{
73                value += rounded_box_shadow_x(point.x, point.y - y, sigma, corner, half_size) * gaussian(y, sigma) * step;
74                y += step;
75            }
76                            
77            return value;
78        }
79        
80        fn box_shadow(lower:vec2, upper:vec2, point:vec2, sigma:float)->float {
81            let query = vec4(point - lower, point - upper);
82            let integral = 0.5 + 0.5 * erf_vec4(query * (sqrt(0.5) / sigma));
83            return (integral.z - integral.x) * (integral.w - integral.y);
84        }
85    }
86    
87    pub Math = {
88        fn rotate_2d(v: vec2, a: float) -> vec2 {
89            let ca = cos(a);
90            let sa = sin(a);
91            return vec2(v.x * ca - v.y * sa, v.x * sa + v.y * ca);
92        }
93        
94        fn random_2d(v: vec2)->float {
95           return fract(sin(dot(v.xy, vec2(12.9898,78.233))) * 43758.5453);
96        }
97    }
98    
99    pub Pal = {
100        
101        fn premul(v: vec4) -> vec4 {
102            return vec4(v.x * v.w, v.y * v.w, v.z * v.w, v.w);
103        }
104        
105        fn iq(t: float, a: vec3, b: vec3, c: vec3, d: vec3) -> vec3 {
106            return a + b * cos(6.28318 * (c * t + d));
107        }
108        
109        fn iq0(t: float) -> vec3 {
110            return mix(vec3(0., 0., 0.), vec3(1., 1., 1.), cos(t * PI) * 0.5 + 0.5);
111        }
112        
113        fn iq1(t: float) -> vec3 {
114            return Pal::iq(t, vec3(0.5, 0.5, 0.5), vec3(0.5, 0.5, 0.5), vec3(1., 1., 1.), vec3(0., 0.33, 0.67));
115        }
116        
117        fn iq2(t: float) -> vec3 {
118            return Pal::iq(t, vec3(0.5, 0.5, 0.5), vec3(0.5, 0.5, 0.5), vec3(1., 1., 1.), vec3(0., 0.1, 0.2));
119        }
120        
121        fn iq3(t: float) -> vec3 {
122            return Pal::iq(t, vec3(0.5, 0.5, 0.5), vec3(0.5, 0.5, 0.5), vec3(1., 1., 1.), vec3(0.3, 0.2, 0.2));
123        }
124        
125        fn iq4(t: float) -> vec3 {
126            return Pal::iq(t, vec3(0.5, 0.5, 0.5), vec3(0.5, 0.5, 0.5), vec3(1., 1., 0.5), vec3(0.8, 0.9, 0.3));
127        }
128        
129        fn iq5(t: float) -> vec3 {
130            return Pal::iq(t, vec3(0.5, 0.5, 0.5), vec3(0.5, 0.5, 0.5), vec3(1., 0.7, 0.4), vec3(0, 0.15, 0.20));
131        }
132        
133        fn iq6(t: float) -> vec3 {
134            return Pal::iq(t, vec3(0.5, 0.5, 0.5), vec3(0.5, 0.5, 0.5), vec3(2., 1.0, 0.), vec3(0.5, 0.2, 0.25));
135        }
136        
137        fn iq7(t: float) -> vec3 {
138            return Pal::iq(t, vec3(0.8, 0.5, 0.4), vec3(0.2, 0.4, 0.2), vec3(2., 1.0, 1.0), vec3(0., 0.25, 0.25));
139        }
140        
141        fn hsv2rgb(c: vec4) -> vec4 { //http://gamedev.stackexchange.com/questions/59797/glsl-shader-change-hue-saturation-brightness
142            let K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
143            let p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
144            return vec4(c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y), c.w);
145        }
146        
147        fn rgb2hsv(c: vec4) -> vec4 {
148            let K: vec4 = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
149            let p: vec4 = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
150            let q: vec4 = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
151            
152            let d: float = q.x - min(q.w, q.y);
153            let e: float = 1.0e-10;
154            return vec4(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x, c.w);
155        }
156    }
157    
158    pub Sdf2d = struct {
159        field pos: vec2
160        field result: vec4
161        field last_pos: vec2
162        field start_pos: vec2
163        field shape: float
164        field clip: float
165        field has_clip: float
166        field old_shape: float
167        field blur: float
168        field aa: float
169        field scale_factor: float
170        field dist: float
171        
172        fn antialias(p: vec2) -> float {
173            return 1.0 / length(vec2(length(dFdx(p)), length(dFdy(p))));
174        }
175        
176        fn viewport(pos: vec2) -> Self {
177            return Self {
178                pos: pos
179                result: vec4(0.)
180                last_pos: vec2(0.)
181                start_pos: vec2(0.)
182                shape: 1e+20
183                clip: -1e+20
184                has_clip: 0.0
185                old_shape: 1e+20
186                blur: 0.00001
187                aa: antialias(pos)
188                scale_factor: 1.0
189                dist: 0.0
190            };
191        }
192        
193        fn translate(inout self, x: float, y: float) -> vec2 {
194            self.pos -= vec2(x, y);
195            return self.pos;
196        }
197        
198        fn rotate(inout self, a: float, x: float, y: float) {
199            let ca = cos(-a);
200            let sa = sin(-a);
201            let p = self.pos - vec2(x, y);
202            self.pos = vec2(p.x * ca - p.y * sa, p.x * sa + p.y * ca) + vec2(x, y);
203        }
204        
205        fn scale(inout self, f: float, x: float, y: float) {
206            self.scale_factor *= f;
207            self.pos = (self.pos - vec2(x, y)) * f + vec2(x, y);
208        }
209        
210        fn clear(inout self, color: vec4) {
211            self.result = vec4(color.rgb * color.a + self.result.rgb * (1.0 - color.a), color.a);
212        }
213        
214        fn calc_blur(inout self, w: float) -> float {
215            let wa = clamp(-w * self.aa, 0.0, 1.0);
216            let wb = 1.0;
217            if self.blur > 0.001 {
218                wb = clamp(-w / self.blur, 0.0, 1.0);
219            }
220            return wa * wb;
221        }
222        
223        fn fill_keep_premul(inout self, source: vec4) -> vec4 {
224            let f = self.calc_blur(self.shape);
225            self.result = source * f + self.result * (1. - source.a * f);
226            if self.has_clip > 0.5 {
227                let f2 = 1.0 - self.calc_blur(-self.clip);
228                self.result = source * f2 + self.result * (1. - source.a * f2);
229            }
230            return self.result;
231        }
232                
233        fn fill_premul(inout self, color: vec4) -> vec4 {
234            self.fill_keep_premul(color);
235            self.old_shape = self.shape = 1e+20;
236            self.clip = -1e+20;
237            self.has_clip = 0.;
238            return self.result;
239        }
240        
241        fn fill_keep(inout self, color: vec4) -> vec4 {
242            return self.fill_keep_premul(vec4(color.rgb * color.a, color.a))
243        }
244        
245        fn fill(inout self, color: vec4) -> vec4 {
246            return self.fill_premul(vec4(color.rgb * color.a, color.a))
247        }
248        
249        fn stroke_keep(inout self, color: vec4, width: float) -> vec4 {
250            let f = self.calc_blur(abs(self.shape) - width / self.scale_factor);
251            let source = vec4(color.rgb * color.a, color.a);
252            let dest = self.result;
253            self.result = source * f + dest * (1.0 - source.a * f);
254            return self.result;
255        }
256        
257        fn stroke(inout self, color: vec4, width: float) -> vec4 {
258            self.stroke_keep(color, width);
259            self.old_shape = self.shape = 1e+20;
260            self.clip = -1e+20;
261            self.has_clip = 0.;
262            return self.result;
263        }
264        
265        fn glow_keep(inout self, color: vec4, width: float) -> vec4 {
266            let f = self.calc_blur(abs(self.shape) - width / self.scale_factor);
267            let source = vec4(color.rgb * color.a, color.a);
268            let dest = self.result;
269            self.result = vec4(source.rgb * f, 0.) + dest;
270            return self.result;
271        }
272        
273        fn glow(inout self, color: vec4, width: float) -> vec4 {
274            self.glow_keep(color, width);
275            self.old_shape = self.shape = 1e+20;
276            self.clip = -1e+20;
277            self.has_clip = 0.;
278            return self.result;
279        }
280        
281        fn union(inout self) {
282            self.old_shape = self.shape = min(self.dist, self.old_shape);
283        }
284        
285        fn intersect(inout self) {
286            self.old_shape = self.shape = max(self.dist, self.old_shape);
287        }
288        
289        fn subtract(inout self) {
290            self.old_shape = self.shape = max(-self.dist, self.old_shape);
291        }
292        
293        fn gloop(inout self, k: float) {
294            let h = clamp(0.5 + 0.5 * (self.old_shape - self.dist) / k, 0.0, 1.0);
295            self.old_shape = self.shape = mix(self.old_shape, self.dist, h) - k * h * (1.0 - h);
296        }
297        
298        fn blend(inout self, k: float) {
299            self.old_shape = self.shape = mix(self.old_shape, self.dist, k);
300        }
301        
302        fn circle(inout self, x: float, y: float, r: float) {
303            let c = self.pos - vec2(x, y);
304            let len = sqrt(c.x * c.x + c.y * c.y);
305            self.dist = (len - r) / self.scale_factor;
306            self.old_shape = self.shape;
307            self.shape = min(self.shape, self.dist);
308        }
309
310        // A distance function for an arc with round caps
311        fn arc_round_caps(
312            inout self,
313            // The x-coordinate of the center of the arc
314            x: float,
315            // The y-coordinate of the center of the arc
316            y: float,
317            // The radius of the the arc
318            radius: float,
319            // The start angle of the arc, in radians
320            start_angle: float,
321            // The end angle of the arc, in radians
322            end_angle: float,
323            // The thickness of the arc
324            thickness: float
325        ) {
326            let p = self.pos - vec2(x, y);
327            let half_angle = (end_angle - start_angle) / 2.0;
328            let p = Math::rotate_2d(p, -start_angle - half_angle);
329            p.x = abs(p.x);
330            let sin_half_angle = sin(half_angle);
331            let cos_half_angle = cos(half_angle);
332            let dist_to_arc = abs(length(p) - radius) - 0.5 * thickness;
333            let cap_center = vec2(sin_half_angle, cos_half_angle) * radius;
334            let dist_to_cap = length(p - cap_center) - 0.5 * thickness;
335            if cos_half_angle * p.x < sin_half_angle * p.y {
336                self.dist = dist_to_arc;
337            } else {
338                self.dist = dist_to_cap;
339            }
340            self.old_shape = self.shape;
341            self.shape = min(self.shape, self.dist);
342        }
343
344        // A distance function for an arc with flat caps
345        fn arc_flat_caps(
346            inout self,
347            // The x-coordinate of the center of the arc
348            x: float,
349            // The y-coordinate of the center of the arc
350            y: float,
351            // The radius of the arc
352            radius: float,
353            // The start angle of the arc, in radians
354            start_angle: float,
355            // The end angle of the arc, in radians
356            end_angle: float,
357            // The thickness of the arc
358            thickness: float
359        ) {
360            let p = self.pos - vec2(x, y);
361            let half_angle = (end_angle - start_angle) / 2.0;
362            let p = Math::rotate_2d(p, -start_angle - half_angle);
363            p.x = abs(p.x);
364            let p = Math::rotate_2d(p, half_angle);
365            let dist_to_arc = abs(length(p) - radius) - thickness * 0.5;
366            let dist_y_to_cap = max(0.0, abs(radius - p.y) - thickness * 0.5);
367            let dist_to_cap =  sign(p.x) * length(vec2(p.x, dist_y_to_cap));
368            self.dist = max(dist_to_arc, dist_to_cap);
369            self.old_shape = self.shape;
370            self.shape = min(self.shape, self.dist);
371        }
372         
373        fn arc2(inout self, x: float, y: float, r: float, s:float, e:float)->vec4{
374            let c = self.pos - vec2(x, y);
375            let pi = 3.141592653589793; // FIX THIS BUG
376            
377            //let circle = (sqrt(c.x * c.x + c.y * c.y) - r)*ang;
378            
379            // ok lets do atan2
380            let ang = (atan(c.y,c.x)+pi)/(2.0*pi);
381            let ces = (e-s)*0.5;
382            let ang2 = 1.0 - abs(ang - ces)+ces
383            return mix(vec4(0.,0.,0.,1.0),vec4(1.0),ang2);
384        }
385        
386        
387        fn hline(inout self, y: float, h:float) {
388            let c = self.pos.y - y;
389            self.dist = -h+abs(c) / self.scale_factor;
390            self.old_shape = self.shape;
391            self.shape = min(self.shape, self.dist);
392        }
393        
394        fn box(inout self, x: float, y: float, w: float, h: float, r: float) {
395            let p = self.pos - vec2(x, y);
396            let size = vec2(0.5 * w, 0.5 * h);
397            let bp = max(abs(p - size.xy) - (size.xy - vec2(2. * r, 2. * r).xy), vec2(0., 0.));
398            self.dist = (length(bp) - 2. * r) / self.scale_factor;
399            self.old_shape = self.shape;
400            self.shape = min(self.shape, self.dist);
401        }
402        
403        fn box_y(inout self, x: float, y: float, w: float, h: float, r_top: float, r_bottom: float) {
404            let size = vec2(0.5 * w, 0.5 * h);
405            let p_r = self.pos - vec2(x, y);
406            let p = abs(p_r - size.xy) - size.xy;
407            
408            let bp_top = max(p + vec2(2. * r_top, 2. * r_top).xy, vec2(0., 0.));
409            let bp_bottom = max(p + vec2(2. * r_bottom, 2. * r_bottom).xy, vec2(0., 0.));
410            
411            self.dist = mix(
412                (length(bp_top) - 2. * r_top),
413                (length(bp_bottom) - 2. * r_bottom),
414                step(0.5 * h, p_r.y)
415            ) / self.scale_factor;
416            
417            self.old_shape = self.shape;
418            self.shape = min(self.shape, self.dist);
419        }
420        
421        fn box_x(inout self, x: float, y: float, w: float, h: float, r_left: float, r_right: float) {
422            let size = vec2(0.5 * w, 0.5 * h);
423            let p_r = self.pos - vec2(x, y);
424            let p = abs(p_r - size.xy) - size.xy;
425            
426            let bp_left = max(p + vec2(2. * r_left, 2. * r_left).xy, vec2(0., 0.));
427            let bp_right = max(p + vec2(2. * r_right, 2. * r_right).xy, vec2(0., 0.));
428            
429            self.dist = mix(
430                (length(bp_left) - 2. * r_left),
431                (length(bp_right) - 2. * r_right),
432                step(0.5 * w, p_r.x)
433            ) / self.scale_factor;
434            
435            self.old_shape = self.shape;
436            self.shape = min(self.shape, self.dist);
437        }
438        
439        fn box_all(
440            inout self,
441            x: float,
442            y: float,
443            w: float,
444            h: float,
445            r_left_top: float,
446            r_right_top: float,
447            r_right_bottom: float,
448            r_left_bottom: float
449        ) {
450            let size = vec2(0.5 * w, 0.5 * h);
451            let p_r = self.pos - vec2(x, y);
452            let p = abs(p_r - size.xy) - size.xy;
453            
454            let bp_lt = max(p + vec2(2. * r_left_top, 2. * r_left_top).xy, vec2(0., 0.));
455            let bp_rt = max(p + vec2(2. * r_right_top, 2. * r_right_top).xy, vec2(0., 0.));
456            let bp_rb = max(p + vec2(2. * r_right_bottom, 2. * r_right_bottom).xy, vec2(0., 0.));
457            let bp_lb = max(p + vec2(2. * r_left_bottom, 2. * r_left_bottom).xy, vec2(0., 0.));
458            
459            self.dist = mix(
460                mix(
461                    (length(bp_lt) - 2. * r_left_top),
462                    (length(bp_lb) - 2. * r_left_bottom),
463                    step(0.5 * h, p_r.y)
464                ),
465                mix(
466                    (length(bp_rt) - 2. * r_right_top),
467                    (length(bp_rb) - 2. * r_right_bottom),
468                    step(0.5 * h, p_r.y)
469                ),
470                step(0.5 * w, p_r.x)
471            ) / self.scale_factor;
472            
473            self.old_shape = self.shape;
474            self.shape = min(self.shape, self.dist);
475        }
476        
477        
478        fn rect(inout self, x: float, y: float, w: float, h: float) {
479            let s = vec2(w, h) * 0.5;
480            let d = abs(vec2(x, y) - self.pos + s) - s;
481            let dm = min(d, vec2(0., 0.));
482            self.dist = max(dm.x, dm.y) + length(max(d, vec2(0., 0.)));
483            self.old_shape = self.shape;
484            self.shape = min(self.shape, self.dist);
485        }
486        
487        fn hexagon(inout self, x: float, y: float, r: float) {
488            let dx = abs(x - self.pos.x) * 1.15;
489            let dy = abs(y - self.pos.y);
490            self.dist = max(dy + cos(60.0 * TORAD) * dx - r, dx - r);
491            self.old_shape = self.shape;
492            self.shape = min(self.shape, self.dist);
493        }
494        
495        fn move_to(inout self, x: float, y: float) {
496            self.last_pos =
497            self.start_pos = vec2(x, y);
498        }
499        
500        fn line_to(inout self, x: float, y: float) {
501            let p = vec2(x, y);
502            
503            let pa = self.pos - self.last_pos;
504            let ba = p - self.last_pos;
505            let h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
506            let s = sign(pa.x * ba.y - pa.y * ba.x);
507            self.dist = length(pa - ba * h) / self.scale_factor;
508            self.old_shape = self.shape;
509            self.shape = min(self.shape, self.dist);
510            self.clip = max(self.clip, self.dist * s);
511            self.has_clip = 1.0;
512            self.last_pos = p;
513        }
514        
515        fn close_path(inout self) {
516            self.line_to(self.start_pos.x, self.start_pos.y);
517        }
518    }
519}