1 /** shader based graphical effects */
2 
3 module re.gfx.effect;
4 
5 import std.string : toStringz;
6 
7 import re.gfx.raytypes;
8 import re.util.hotreload;
9 static import raylib;
10 
11 /// represents an effect
12 class Effect {
13     /// the shader program for the effect
14     Shader shader;
15     /// the tint color
16     Color color;
17     /// a reloadable shader if any
18     ReloadableShader reloadable_shader;
19 
20     this() {
21         this(Shader.init);
22     }
23 
24     this(Shader shader, Color color = Colors.WHITE) {
25         this.shader = shader;
26         this.color = color;
27     }
28 
29     this(ReloadableShader reloadable_shader, Color color = Colors.WHITE) {
30         this.reloadable_shader = reloadable_shader;
31         auto shader = reloadable_shader.reload();
32         this(shader, color);
33     }
34 
35     public void update() {
36         // update the effect
37         // if hot reload is enabled
38         if (reloadable_shader) {
39             // check if we need to reload the shader
40             if (reloadable_shader.changed()) {
41                 // shader changed, we load it again
42                 reload_shader();
43             }
44         }
45     }
46 
47     protected void reload_shader() {
48         shader = reloadable_shader.reload();
49     }
50 
51     /// set a uniform value to an immeditae value
52     public bool set_shader_var_imm(T)(string name, T value) {
53         T var = value;
54         return set_shader_var(name, var);
55     }
56 
57     /// set a uniform value to a variable by reference
58     public bool set_shader_var(T)(string name, ref T value) {
59         auto loc = get_shader_loc(name);
60         if (loc < 0) {
61             // if the shader variable doesn't exist, return false
62             return false;
63         }
64 
65         // figure out the uniform var type
66         raylib.ShaderUniformDataType val_type;
67         alias vartype = raylib.ShaderUniformDataType;
68         static if (is(T == float)) {
69             val_type = vartype.SHADER_UNIFORM_FLOAT;
70         } else static if (is(T == int)) {
71             val_type = vartype.SHADER_UNIFORM_INT;
72         } else static if (is(T == float[2])) {
73             val_type = vartype.SHADER_UNIFORM_VEC2;
74         } else static if (is(T == float[3])) {
75             val_type = vartype.SHADER_UNIFORM_VEC3;
76         } else static if (is(T == float[4])) {
77             val_type = vartype.SHADER_UNIFORM_VEC4;
78         } else static if (is(T == int[2])) {
79             val_type = vartype.SHADER_UNIFORM_IVEC2;
80         } else static if (is(T == int[3])) {
81             val_type = vartype.SHADER_UNIFORM_IVEC3;
82         } else static if (is(T == int[4])) {
83             val_type = vartype.SHADER_UNIFORM_IVEC4;
84         } else {
85             static assert(0, "unrecognized shader value data type");
86         }
87         raylib.SetShaderValue(shader, loc, &value, val_type);
88         return true;
89     }
90 
91     /// get location of uniform in shader. returns -1 if not found
92     public int get_shader_loc(string name) {
93         return raylib.GetShaderLocation(shader, name.toStringz);
94     }
95 }