makepad_render/
shader.rs

1
2// Shader AST typedefs
3
4pub use makepad_shader_ast::*;
5pub use crate::cx::*;
6pub use crate::math::*;
7pub use crate::colors::*;
8use std::any::TypeId;
9
10#[derive(Hash, PartialEq, Copy, Clone)]
11pub struct InstanceColor(pub TypeId);
12
13#[derive(Hash, PartialEq, Copy, Clone)]
14pub struct InstanceVec4(pub TypeId);
15
16#[derive(Hash, PartialEq, Copy, Clone)]
17pub struct InstanceVec3(pub TypeId);
18
19#[derive(Hash, PartialEq, Copy, Clone)]
20pub struct InstanceVec2(pub TypeId);
21
22#[derive(Hash, PartialEq, Copy, Clone)]
23pub struct InstanceFloat(pub TypeId);
24
25#[derive(Hash, PartialEq, Copy, Clone)]
26pub struct UniformColor(pub TypeId);
27
28#[derive(Hash, PartialEq, Copy, Clone)]
29pub struct UniformVec4(pub TypeId);
30
31#[derive(Hash, PartialEq, Copy, Clone)]
32pub struct UniformVec3(pub TypeId);
33
34#[derive(Hash, PartialEq, Copy, Clone)]
35pub struct UniformVec2(pub TypeId);
36
37#[derive(Hash, PartialEq, Copy, Clone)]
38pub struct UniformFloat(pub TypeId);
39
40pub struct UniqueId(pub TypeId);
41
42#[macro_export]
43macro_rules!uid { 
44    () => {{
45        struct Unique{};
46        UniqueId(std::any::TypeId::of::<Unique>()).into()
47    }}
48}
49
50impl InstanceColor{
51    pub fn shader_type(&self) -> String{"vec4".to_string()}
52    pub fn instance_type(&self) -> InstanceType{InstanceType::Color(*self)}
53    pub fn var_store(&self) -> ShVarStore{ShVarStore::Instance(self.instance_type())}
54}
55
56impl Into<InstanceColor> for UniqueId{
57    fn into(self) -> InstanceColor{InstanceColor(self.0)}
58}
59
60impl InstanceVec4{
61    pub fn shader_type(&self) -> String{"vec4".to_string()}
62    pub fn instance_type(&self) -> InstanceType{InstanceType::Vec4(*self)}
63    pub fn var_store(&self) -> ShVarStore{ShVarStore::Instance(self.instance_type())}
64}
65
66impl Into<InstanceVec4> for UniqueId{
67    fn into(self) -> InstanceVec4{InstanceVec4(self.0)}
68}
69
70impl InstanceVec3{
71    pub fn shader_type(&self) -> String{"vec3".to_string()}
72    pub fn instance_type(&self) -> InstanceType{InstanceType::Vec3(*self)}
73    pub fn var_store(&self) -> ShVarStore{ShVarStore::Instance(self.instance_type())}
74}
75
76impl Into<InstanceVec3> for UniqueId{
77    fn into(self) -> InstanceVec3{InstanceVec3(self.0)}
78}
79
80impl InstanceVec2{
81    pub fn shader_type(&self) -> String{"vec2".to_string()}
82    pub fn instance_type(&self) -> InstanceType{InstanceType::Vec2(*self)}
83    pub fn var_store(&self) -> ShVarStore{ShVarStore::Instance(self.instance_type())}
84}
85
86impl Into<InstanceVec2> for UniqueId{
87    fn into(self) -> InstanceVec2{InstanceVec2(self.0)}
88}
89
90impl InstanceFloat{
91    pub fn shader_type(&self) -> String{"float".to_string()}
92    pub fn instance_type(&self) -> InstanceType{InstanceType::Float(*self)}
93    pub fn var_store(&self) -> ShVarStore{ShVarStore::Instance(self.instance_type())}
94}
95
96impl Into<InstanceFloat> for UniqueId{
97    fn into(self) -> InstanceFloat{InstanceFloat(self.0)}
98}
99
100impl UniformColor{
101    pub fn shader_type(&self) -> String{"vec4".to_string()}
102    pub fn uniform_type(&self) -> UniformType{UniformType::Color(*self)}
103    pub fn var_store(&self) -> ShVarStore{ShVarStore::Uniform(self.uniform_type())}
104}
105
106impl Into<UniformColor> for UniqueId{
107    fn into(self) -> UniformColor{UniformColor(self.0)}
108}
109
110impl UniformVec4{
111    pub fn shader_type(&self) -> String{"vec4".to_string()}
112    pub fn uniform_type(&self) -> UniformType{UniformType::Vec4(*self)}
113    pub fn var_store(&self) -> ShVarStore{ShVarStore::Uniform(self.uniform_type())}
114}
115
116impl Into<UniformVec4> for UniqueId{
117    fn into(self) -> UniformVec4{UniformVec4(self.0)}
118}
119
120impl UniformVec3{
121    pub fn shader_type(&self) -> String{"vec3".to_string()}
122    pub fn uniform_type(&self) -> UniformType{UniformType::Vec3(*self)}
123    pub fn var_store(&self) -> ShVarStore{ShVarStore::Uniform(self.uniform_type())}
124}
125
126impl Into<UniformVec3> for UniqueId{
127    fn into(self) -> UniformVec3{UniformVec3(self.0)}
128}
129
130impl UniformVec2{
131    pub fn shader_type(&self) -> String{"vec2".to_string()}
132    pub fn uniform_type(&self) -> UniformType{UniformType::Vec2(*self)}
133    pub fn var_store(&self) -> ShVarStore{ShVarStore::Uniform(self.uniform_type())}
134}
135
136impl Into<UniformVec2> for UniqueId{
137    fn into(self) -> UniformVec2{UniformVec2(self.0)}
138}
139
140impl UniformFloat{
141    pub fn shader_type(&self) -> String{"float".to_string()}
142    pub fn uniform_type(&self) -> UniformType{UniformType::Float(*self)}
143    pub fn var_store(&self) -> ShVarStore{ShVarStore::Uniform(self.uniform_type())}
144}
145
146impl Into<UniformFloat> for UniqueId{
147    fn into(self) -> UniformFloat{UniformFloat(self.0)}
148}
149
150#[derive(Default, Copy, Clone, PartialEq)]
151pub struct Shader {
152    pub shader_id: Option<(usize, usize)>,
153} 
154
155#[derive(Default, Clone)]
156pub struct RectInstanceProps {
157    pub x: Option<usize>,
158    pub y: Option<usize>,
159    pub w: Option<usize>,
160    pub h: Option<usize>,
161}
162
163impl RectInstanceProps {
164    pub fn construct(sg: &ShaderGen, instances: &Vec<ShVar>) -> RectInstanceProps {
165        let mut x = None;
166        let mut y = None;
167        let mut w = None;
168        let mut h = None;
169        let mut slot = 0;
170        for inst in instances {
171            match inst.name.as_ref() {
172                "x" => x = Some(slot),
173                "y" => y = Some(slot),
174                "w" => w = Some(slot),
175                "h" => h = Some(slot),
176                _ => ()
177            }
178            slot += sg.get_type_slots(&inst.ty);
179        };
180        RectInstanceProps {
181            x: x,
182            y: y,
183            w: w,
184            h: h
185        }
186    }
187}
188
189#[derive(Clone)]
190pub struct InstanceProp {
191    pub name: String,
192    pub ident: InstanceType,
193    pub offset: usize,
194    pub slots: usize
195}
196
197#[derive(Default, Clone)]
198pub struct InstanceProps {
199    pub props: Vec<InstanceProp>,
200    pub total_slots: usize,
201}
202
203#[derive(Clone)]
204pub struct UniformProp {
205    pub name: String,
206    pub ident: UniformType,
207    pub offset: usize,
208    pub slots: usize
209}
210
211#[derive(Default, Clone)]
212pub struct UniformProps {
213    pub props: Vec<UniformProp>,
214    pub total_slots: usize,
215}
216
217#[derive(Clone)]
218pub struct NamedProp {
219    pub name: String,
220    pub offset: usize,
221    pub slots: usize
222}
223
224#[derive(Default, Clone)]
225pub struct NamedProps {
226    pub props: Vec<NamedProp>,
227    pub total_slots: usize,
228}
229
230impl NamedProps {
231    pub fn construct(sg: &ShaderGen, in_props: &Vec<ShVar>)->NamedProps{
232        let mut offset = 0;
233        let mut out_props = Vec::new();
234        for prop in in_props {
235            let slots = sg.get_type_slots(&prop.ty);
236            out_props.push(NamedProp {
237                name: prop.name.clone(),
238                offset: offset,
239                slots: slots
240            });
241            offset += slots
242        };
243        NamedProps {
244            props: out_props,
245            total_slots: offset
246        }
247    }
248}
249
250impl InstanceProps {
251    pub fn construct(sg: &ShaderGen, in_props: &Vec<ShVar>)->InstanceProps{
252        let mut offset = 0;
253        let mut out_props = Vec::new();
254        for prop in in_props {
255            let slots = sg.get_type_slots(&prop.ty);
256            match &prop.store{
257                ShVarStore::Instance(t)=>{
258                    out_props.push(InstanceProp {
259                        ident: t.clone(),
260                        name: prop.name.clone(),
261                        offset: offset,
262                        slots: slots
263                    })
264                },
265                _=>panic!("Non instance in props")
266            }
267            offset += slots
268        };
269        InstanceProps {
270            props: out_props,
271            total_slots: offset
272        }
273    }
274}
275
276impl UniformProps{
277    pub fn construct(sg: &ShaderGen, in_props: &Vec<ShVar>)->UniformProps{
278        let mut out_props = Vec::new();
279        let mut offset = 0;
280    
281        for prop in in_props {
282            let slots = sg.get_type_slots(&prop.ty);
283            
284            if (offset & 3) + slots > 4 { // goes over the boundary
285                offset += 4 - (offset & 3); // make jump to new slot
286            }
287            if slots == 2 && (offset & 1) != 0 {
288                panic!("Please re-order uniform {} to be size-2 aligned", prop.name);
289            }
290            match &prop.store{
291                ShVarStore::Uniform(t)=>{
292                    out_props.push(UniformProp {
293                        ident:t.clone(),  
294                        name: prop.name.clone(),
295                        offset: offset,
296                        slots: slots
297                    })
298                },
299                _=>panic!("Non uniform in props")
300            }
301            offset += slots
302        };
303        if offset & 3 > 0 {
304            offset += 4 - (offset & 3);
305        }
306        UniformProps {
307            props: out_props,
308            total_slots: offset
309        }
310    }
311
312    pub fn find_zbias_uniform_prop(&self) -> Option<usize> {
313        for prop in &self.props {
314            if prop.name == "zbias" {
315                return Some(prop.offset)
316            }
317        }
318        return None
319    }
320} 
321 
322#[derive(Default, Clone)]
323pub struct CxShaderMapping {
324    pub instance_slots: usize,
325    pub geometry_slots: usize,
326    pub geometries: Vec<ShVar>,
327    pub instances: Vec<ShVar>,
328    pub draw_uniforms: Vec<ShVar>,
329    pub view_uniforms: Vec<ShVar>,
330    pub pass_uniforms: Vec<ShVar>,
331    pub uniforms: Vec<ShVar>,
332    pub texture_slots: Vec<ShVar>,
333    pub rect_instance_props: RectInstanceProps,
334    pub uniform_props: UniformProps,
335    pub instance_props: InstanceProps,
336}
337
338#[derive(Default, Clone)]
339pub struct CxShader {
340    pub name: String,
341    pub shader_gen: ShaderGen,
342    pub platform: Option<CxPlatformShader>,
343    pub mapping: CxShaderMapping
344}
345
346impl CxShader {
347    
348    pub fn def_builtins(sg: ShaderGen) -> ShaderGen {
349        sg.compose(
350            ShAst {
351                types: vec![
352                    ShType {name: "float".to_string(), slots: 1, prim: true, fields: Vec::new()},
353                    ShType {name: "int".to_string(), slots: 1, prim: true, fields: Vec::new()},
354                    ShType {name: "bool".to_string(), slots: 1, prim: true, fields: Vec::new()},
355                    ShType {
356                        name: "vec2".to_string(),
357                        slots: 2,
358                        prim: true,
359                        fields: vec![ShTypeField::new("x", "float"), ShTypeField::new("y", "float")]
360                    },
361                    ShType {
362                        name: "vec3".to_string(),
363                        slots: 3,
364                        prim: true,
365                        fields: vec![ShTypeField::new("x", "float"), ShTypeField::new("y", "float"), ShTypeField::new("z", "float")]
366                    },
367                    ShType {
368                        name: "vec4".to_string(),
369                        slots: 4,
370                        prim: true,
371                        fields: vec![ShTypeField::new("x", "float"), ShTypeField::new("y", "float"), ShTypeField::new("z", "float"), ShTypeField::new("w", "float")]
372                    },
373                    ShType {
374                        name: "mat2".to_string(),
375                        slots: 4,
376                        prim: true,
377                        fields: vec![
378                            ShTypeField::new("a", "float"),
379                            ShTypeField::new("b", "float"),
380                            ShTypeField::new("c", "float"),
381                            ShTypeField::new("d", "float")
382                        ]
383                    },
384                    ShType {
385                        name: "mat3".to_string(),
386                        slots: 9,
387                        prim: true,
388                        fields: vec![
389                            ShTypeField::new("a", "float"),
390                            ShTypeField::new("b", "float"),
391                            ShTypeField::new("c", "float"),
392                            ShTypeField::new("d", "float"),
393                            ShTypeField::new("e", "float"),
394                            ShTypeField::new("f", "float"),
395                            ShTypeField::new("g", "float"),
396                            ShTypeField::new("h", "float"),
397                            ShTypeField::new("i", "float")
398                        ]
399                    },
400                    ShType {
401                        name: "mat4".to_string(),
402                        slots: 16,
403                        prim: true,
404                        fields: vec![
405                            ShTypeField::new("a", "float"),
406                            ShTypeField::new("b", "float"),
407                            ShTypeField::new("c", "float"),
408                            ShTypeField::new("d", "float"),
409                            ShTypeField::new("e", "float"),
410                            ShTypeField::new("f", "float"),
411                            ShTypeField::new("g", "float"),
412                            ShTypeField::new("h", "float"),
413                            ShTypeField::new("i", "float"),
414                            ShTypeField::new("j", "float"),
415                            ShTypeField::new("k", "float"),
416                            ShTypeField::new("l", "float"),
417                            ShTypeField::new("m", "float"),
418                            ShTypeField::new("n", "float"),
419                            ShTypeField::new("o", "float"),
420                            ShTypeField::new("p", "float")
421                        ]
422                    },
423                ],
424                vars: Vec::new(),
425                fns: vec![
426                    // shorthand typed:
427                    // T - generic
428                    // O - optional
429                    // F - float-like (float, vec2, vec3, etc)
430                    // B - bool-vector (bvecn)
431                    
432                    ShFn {name: "sizeof".to_string(), args: vec![ShFnArg::new("type", "T")], ret: "int".to_string(), block: None},
433                    ShFn {name: "color".to_string(), args: vec![ShFnArg::new("color", "string")], ret: "vec4".to_string(), block: None},
434                    
435                    ShFn {name: "radians".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
436                    ShFn {name: "degrees".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
437                    
438                    ShFn {name: "sin".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
439                    ShFn {name: "cos".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
440                    ShFn {name: "tan".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
441                    ShFn {name: "asin".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
442                    ShFn {name: "acos".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
443                    ShFn {name: "atan".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "T".to_string(), block: None},
444                    
445                    ShFn {name: "pow".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "T".to_string(), block: None},
446                    ShFn {name: "exp".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
447                    ShFn {name: "log".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
448                    ShFn {name: "exp2".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
449                    ShFn {name: "log2".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
450                    
451                    ShFn {name: "sqrt".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
452                    ShFn {name: "inversesqrt".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
453                    
454                    ShFn {name: "abs".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
455                    ShFn {name: "sign".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
456                    ShFn {name: "floor".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
457                    ShFn {name: "ceil".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
458                    ShFn {name: "fract".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
459                    
460                    ShFn {name: "fmod".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "T".to_string(), block: None},
461                    ShFn {name: "min".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "T".to_string(), block: None},
462                    ShFn {name: "max".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "T".to_string(), block: None},
463                    ShFn {name: "clamp".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("mi", "T"), ShFnArg::new("ma", "T")], ret: "T".to_string(), block: None},
464                    
465                    ShFn {name: "mix".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T"), ShFnArg::new("t", "F")], ret: "T".to_string(), block: None},
466                    ShFn {name: "step".to_string(), args: vec![ShFnArg::new("e", "T"), ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
467                    ShFn {name: "smoothstep".to_string(), args: vec![ShFnArg::new("e0", "F"), ShFnArg::new("e1", "F"), ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
468                    
469                    ShFn {name: "length".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "float".to_string(), block: None},
470                    ShFn {name: "distance".to_string(), args: vec![ShFnArg::new("p0", "T"), ShFnArg::new("p1", "T")], ret: "float".to_string(), block: None},
471                    ShFn {name: "dot".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "float".to_string(), block: None},
472                    ShFn {name: "cross".to_string(), args: vec![ShFnArg::new("x", "vec3"), ShFnArg::new("y", "vec3")], ret: "vec3".to_string(), block: None},
473                    ShFn {name: "normalize".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
474                    
475                    ShFn {name: "faceforward".to_string(), args: vec![ShFnArg::new("n", "T"), ShFnArg::new("i", "T"), ShFnArg::new("nref", "T")], ret: "T".to_string(), block: None},
476                    ShFn {name: "reflect".to_string(), args: vec![ShFnArg::new("i", "T"), ShFnArg::new("n", "T")], ret: "T".to_string(), block: None},
477                    ShFn {name: "refract".to_string(), args: vec![ShFnArg::new("i", "T"), ShFnArg::new("n", "T"), ShFnArg::new("eta", "T")], ret: "T".to_string(), block: None},
478                    
479                    ShFn {name: "matrix_comp_mult".to_string(), args: vec![ShFnArg::new("a", "mat4"), ShFnArg::new("b", "mat4")], ret: "mat4".to_string(), block: None},
480                    
481                    ShFn {name: "less_than".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "B".to_string(), block: None},
482                    ShFn {name: "less_than_equal".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "B".to_string(), block: None},
483                    ShFn {name: "greater_than".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "B".to_string(), block: None},
484                    ShFn {name: "greater_than_equal".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "B".to_string(), block: None},
485                    ShFn {name: "equal".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "B".to_string(), block: None},
486                    ShFn {name: "not_equal".to_string(), args: vec![ShFnArg::new("x", "T"), ShFnArg::new("y", "T")], ret: "B".to_string(), block: None},
487                    
488                    ShFn {name: "any".to_string(), args: vec![ShFnArg::new("x", "B")], ret: "bool".to_string(), block: None},
489                    ShFn {name: "all".to_string(), args: vec![ShFnArg::new("x", "B")], ret: "bool".to_string(), block: None},
490                    ShFn {name: "not".to_string(), args: vec![ShFnArg::new("x", "B")], ret: "B".to_string(), block: None},
491                    
492                    ShFn {name: "dfdx".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
493                    ShFn {name: "dfdy".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
494                    ShFn {name: "fwidth".to_string(), args: vec![ShFnArg::new("x", "T")], ret: "T".to_string(), block: None},
495                    
496                    ShFn {name: "sample2d".to_string(), args: vec![ShFnArg::new("texture", "texture2d"), ShFnArg::new("coord", "vec2")], ret: "vec4".to_string(), block: None},
497                    /*
498                    ShFn{name:"texture2DLod".to_string(), args:vec![ShFnArg::new("sampler","sampler2D"), ShFnArg::new("coord","vec2"), ShFnArg::new("lod","float")], ret:"vec4".to_string(), block:None},
499                    ShFn{name:"texture2DProjLod".to_string(), args:vec![ShFnArg::new("sampler","sampler2D"), ShFnArg::new("coord","vec2"), ShFnArg::new("lod","float")], ret:"vec4".to_string(), block:None},
500                    ShFn{name:"textureCubeLod".to_string(), args:vec![ShFnArg::new("sampler","samplerCube"), ShFnArg::new("coord","vec3"), ShFnArg::new("lod","float")], ret:"vec4".to_string(), block:None},
501                    ShFn{name:"texture2DProj".to_string(), args:vec![ShFnArg::new("sampler","sampler2D"), ShFnArg::new("coord","vec2"), ShFnArg::new("bias","O")], ret:"vec4".to_string(), block:None},
502                    ShFn{name:"textureCube".to_string(), args:vec![ShFnArg::new("sampler","samplerCube"), ShFnArg::new("coord","vec3"), ShFnArg::new("bias","O")], ret:"vec4".to_string(), block:None},
503                    */
504                ],
505                consts: Vec::new()
506            }
507        )
508    }
509    
510    pub fn def_df(sg: ShaderGen) -> ShaderGen {
511        sg.compose(shader_ast!({
512            const PI: float = 3.141592653589793;
513            const E: float = 2.718281828459045;
514            const LN2: float = 0.6931471805599453;
515            const LN10: float = 2.302585092994046;
516            const LOG2E: float = 1.4426950408889634;
517            const LOG10E: float = 0.4342944819032518;
518            const SQRT1_2: float = 0.70710678118654757;
519            const TORAD: float = 0.017453292519943295;
520            const GOLDEN: float = 1.618033988749895;
521            
522            let df_pos: vec2<Local>;
523            let df_result: vec4<Local>;
524            let df_last_pos: vec2<Local>;
525            let df_start_pos: vec2<Local>;
526            let df_shape: float<Local>;
527            let df_clip: float<Local>;
528            let df_has_clip: float<Local>;
529            let df_old_shape: float<Local>;
530            let df_blur: float<Local>;
531            let df_aa: float<Local>;
532            let df_scale: float<Local>;
533            let df_field: float<Local>;
534            
535            fn df_iq_pal(t: float, a: vec3, b: vec3, c: vec3, d: vec3) -> vec3 {
536                return a + b * cos(6.28318 * (c * t + d));
537            }
538            
539            fn df_iq_pal0(t: float) -> vec3 {
540                return mix(vec3(0., 0., 0.), vec3(1., 1., 1.), cos(t * PI) * 0.5 + 0.5)
541            }
542            
543            fn df_iq_pal1(t: float) -> vec3 {
544                return df_iq_pal(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));
545            }
546            
547            fn df_iq_pal2(t: float) -> vec3 {
548                return df_iq_pal(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));
549            }
550            
551            fn df_iq_pal3(t: float) -> vec3 {
552                return df_iq_pal(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));
553            }
554            
555            fn df_iq_pal4(t: float) -> vec3 {
556                return df_iq_pal(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));
557            }
558            
559            fn df_iq_pal5(t: float) -> vec3 {
560                return df_iq_pal(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));
561            }
562            
563            fn df_iq_pal6(t: float) -> vec3 {
564                return df_iq_pal(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));
565            }
566            
567            fn df_iq_pal7(t: float) -> vec3 {
568                return df_iq_pal(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));
569            }
570            
571            fn df_viewport(pos: vec2) -> vec2 {
572                df_pos = pos;
573                df_result = vec4(0., 0., 0., 0.);
574                df_old_shape =
575                df_shape = 1e+20;
576                df_clip = -1e+20;
577                df_blur = 0.00001;
578                df_aa = df_antialias(pos);
579                df_scale = 1.0;
580                df_field = 0.0;
581                df_clip = 0.0;
582                df_has_clip = 0.0;
583                return df_pos;
584            }
585            
586            fn df_antialias(p: vec2) -> float {
587                return 1.0 / length(vec2(length(dfdx(p)), length(dfdy(p))));
588            }
589            
590            fn df_translate(x: float, y: float) -> vec2 {
591                df_pos -= vec2(x, y);
592                return df_pos;
593            }
594            
595            fn df_rotate(a: float, x: float, y: float) {
596                let ca: float = cos(-a);
597                let sa: float = sin(-a);
598                let p: vec2 = df_pos - vec2(x, y);
599                df_pos = vec2(p.x * ca - p.y * sa, p.x * sa + p.y * ca) + vec2(x, y);
600            }
601            
602            fn df_scale(f: float, x: float, y: float) {
603                df_scale *= f;
604                df_pos = (df_pos - vec2(x, y)) * f + vec2(x, y);
605            }
606            
607            fn df_clear(color: vec4) {
608                df_result = vec4(color.rgb * color.a + df_result.rgb * (1.0 - color.a), color.a);
609            }
610            
611            fn df_calc_blur(w: float) -> float {
612                let wa: float = clamp(-w * df_aa, 0.0, 1.0);
613                let wb: float = 1.0;
614                if df_blur > 0.001 {
615                    wb = clamp(-w / df_blur, 0.0, 1.0)
616                }
617                return wa * wb;
618            }
619            
620            fn df_fill_keep(color: vec4) -> vec4 {
621                let f: float = df_calc_blur(df_shape);
622                let source: vec4 = vec4(color.rgb * color.a, color.a);
623                df_result = source * f + df_result * (1. - source.a * f);
624                if df_has_clip > 0.5 {
625                    let f2: float = 1. - df_calc_blur(-df_clip);
626                    df_result = source * f2 + df_result * (1. - source.a * f2);
627                }
628                return df_result;
629            }
630            
631            fn df_fill(color: vec4) -> vec4 {
632                df_fill_keep(color);
633                df_old_shape = df_shape = 1e+20;
634                df_clip = -1e+20;
635                df_has_clip = 0.;
636                return df_result;
637            }
638            
639            fn df_stroke_keep(color: vec4, width: float) -> vec4 {
640                let f: float = df_calc_blur(abs(df_shape) - width / df_scale);
641                let source: vec4 = vec4(color.rgb * color.a, color.a);
642                let dest: vec4 = df_result;
643                df_result = source * f + dest * (1.0 - source.a * f);
644                return df_result;
645            }
646            
647            fn df_stroke(color: vec4, width: float) -> vec4 {
648                df_stroke_keep(color, width);
649                df_old_shape = df_shape = 1e+20;
650                df_clip = -1e+20;
651                df_has_clip = 0.;
652                return df_result;
653            }
654            
655            fn df_glow_keep(color: vec4, width: float) -> vec4 {
656                let f: float = df_calc_blur(abs(df_shape) - width / df_scale);
657                let source: vec4 = vec4(color.rgb * color.a, color.a);
658                let dest: vec4 = df_result;
659                df_result = vec4(source.rgb * f, 0.) + dest;
660                return df_result;
661            }
662            
663            fn df_glow(color: vec4, width: float) -> vec4 {
664                df_glow_keep(color, width);
665                df_old_shape = df_shape = 1e+20;
666                df_clip = -1e+20;
667                df_has_clip = 0.;
668                return df_result;
669            }
670            
671            fn df_union() {
672                df_old_shape = df_shape = min(df_field, df_old_shape);
673            }
674            
675            fn df_intersect() {
676                df_old_shape = df_shape = max(df_field, df_old_shape);
677            }
678            
679            fn df_subtract() {
680                df_old_shape = df_shape = max(-df_field, df_old_shape);
681            }
682            
683            fn df_gloop(k: float) {
684                let h: float = clamp(0.5 + 0.5 * (df_old_shape - df_field) / k, 0.0, 1.0);
685                df_old_shape = df_shape = mix(df_old_shape, df_field, h) - k * h * (1.0 - h);
686            }
687            
688            fn df_blend(k: float) {
689                df_old_shape = df_shape = mix(df_old_shape, df_field, k);
690            }
691            
692            fn df_circle(x: float, y: float, r: float) {
693                let c: vec2 = df_pos - vec2(x, y);
694                df_field = (length(c.xy) - r) / df_scale;
695                df_old_shape = df_shape;
696                df_shape = min(df_shape, df_field);
697            }
698            
699            fn df_box(x: float, y: float, w: float, h: float, r: float) {
700                let p: vec2 = df_pos - vec2(x, y);
701                let size: vec2 = vec2(0.5 * w, 0.5 * h);
702                let bp: vec2 = max(abs(p - size.xy) - (size.xy - vec2(2. * r, 2. * r).xy), vec2(0., 0.));
703                df_field = (length(bp) - 2. * r) / df_scale;
704                df_old_shape = df_shape;
705                df_shape = min(df_shape, df_field);
706            }
707            
708            fn df_rect(x: float, y: float, w: float, h: float) {
709                let s: vec2 = vec2(w, h) * 0.5;
710                let d: vec2 = abs(vec2(x, y) - df_pos + s) - s;
711                let dm: vec2 = min(d, vec2(0., 0.));
712                df_field = max(dm.x, dm.y) + length(max(d, vec2(0., 0.)));
713                df_old_shape = df_shape;
714                df_shape = min(df_shape, df_field);
715            }
716            
717            fn df_move_to(x: float, y: float) {
718                df_last_pos =
719                df_start_pos = vec2(x, y);
720            }
721            
722            fn df_line_to(x: float, y: float) {
723                let p: vec2 = vec2(x, y);
724                
725                let pa: vec2 = df_pos - df_last_pos;
726                let ba: vec2 = p - df_last_pos;
727                let h: float = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
728                let s: float = sign(pa.x * ba.y - pa.y * ba.x);
729                df_field = length(pa - ba * h) / df_scale;
730                df_old_shape = df_shape;
731                df_shape = min(df_shape, df_field);
732                df_clip = max(df_clip, df_field * s);
733                df_has_clip = 1.0;
734                df_last_pos = p;
735            }
736            
737            fn df_close_path() {
738                df_line_to(df_start_pos.x, df_start_pos.y);
739            }
740            
741            fn df_hsv2rgb(c: vec4) -> vec4 { //http://gamedev.stackexchange.com/questions/59797/glsl-shader-change-hue-saturation-brightness
742                let K: vec4 = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
743                let p: vec4 = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
744                return vec4(c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y), c.w);
745            }
746            
747            fn df_rgb2hsv(c: vec4) -> vec4 {
748                let K: vec4 = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
749                let p: vec4 = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
750                let q: vec4 = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
751                
752                let d: float = q.x - min(q.w, q.y);
753                let e: float = 1.0e-10;
754                return vec4(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x, c.w);
755            }
756        }))
757    }
758}