1 module ecs_utils.gfx.material;
2
3 import bindbc.sdl;
4
5 import bubel.ecs.std;
6
7 import ecs_utils.gfx.shader;
8
9 version(WebAssembly)import glad.gl.gles2;
10 else version(Android)import glad.gl.gles2;
11 else import glad.gl.gl;
12
13 //import mutils.serializer.json;
14
15 struct Material
16 {
17
18 void create() nothrow
19 {
20 data = Mallocator.make!Data;
21 }
22
23 bool load(const char[] path) nothrow
24 {
25 struct LoadData
26 {
27 @("malloc") string blend_mode;
28 @("malloc") string vertex;
29 @("malloc") string fragment;
30
31 void dispose() nothrow
32 {
33 //if(blend_mode)Mallocator.instance.dispose(cast(char[])blend_mode);
34 //if(vertex)Mallocator.instance.dispose(cast(char[])vertex);
35 //if(fragment)Mallocator.instance.dispose(cast(char[])fragment);
36 }
37 }
38
39 char[] cpath = (cast(char*)alloca(path.length+1))[0..path.length+1];
40 cpath[0..$-1] = path[0..$];
41 cpath[$-1] = 0;
42
43 SDL_RWops* file = SDL_RWFromFile(cpath.ptr,"r");
44 if(file)
45 {
46 size_t size = cast(size_t)SDL_RWsize(file);
47 char[] buffer = Mallocator.makeArray!char(size);
48 SDL_RWread(file,buffer.ptr,size,1);
49
50 LoadData load_data;
51 scope(exit)load_data.dispose();
52
53 /*JSONSerializer serializer = Mallocator.make!JSONSerializer;
54 scope(exit)Mallocator.dispose(serializer);
55 serializer.serialize!(Load.yes, true)(load_data,buffer);*/
56
57 //if(__ecs_used_backend == Backend.opengl)
58 {
59 Shader vsh;
60 vsh.load(load_data.vertex);
61 vsh.compile();
62
63 Shader fsh;
64 fsh.load(load_data.fragment);
65 fsh.compile();
66
67 Material.ShaderModule[1] modules = [Material.ShaderModule(vsh,fsh)];
68
69 attachModules(modules);
70 }
71
72 SDL_RWclose(file);
73 load_data.dispose();
74 return true;
75 }
76 else return false;
77 }
78
79 void bind() nothrow
80 {
81 final switch(data.blend_mode)
82 {
83 case BlendMode.mixed:
84 glDepthMask(0);
85 glEnable(GL_BLEND);
86 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
87 break;
88 case BlendMode.opaque:
89 glDepthMask(1);
90 glDisable(GL_BLEND);
91 break;
92 case BlendMode.additive:
93 glDepthMask(0);
94 glEnable(GL_BLEND);
95 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
96 //glBlendFunc(GL_ONE, GL_ONE);
97 break;
98 }
99
100 glUseProgram(data.modules[0].gl_handle);
101 }
102
103 enum BlendMode
104 {
105 opaque,
106 additive,
107 mixed
108 }
109
110 enum TransformMode
111 {
112 position,
113 matrix
114 }
115
116 struct ShaderModule
117 {
118 Shader fragment_shader;
119 Shader vertex_shader;
120 uint gl_handle;
121 }
122
123 void attachModules(scope ShaderModule[] modules) nothrow
124 {
125 data.modules = Mallocator.makeArray(modules);
126 }
127
128 bool compile() nothrow
129 {
130 foreach(ref module_;data.modules)
131 {
132 module_.gl_handle = glCreateProgram();
133 glAttachShader(module_.gl_handle, module_.vertex_shader.data.gl_handle);
134 glAttachShader(module_.gl_handle, module_.fragment_shader.data.gl_handle);
135 }
136
137 return true;
138 }
139
140 void bindAttribLocation(const char* name, uint location) nothrow
141 {
142 foreach(ref module_;data.modules)
143 {
144 glBindAttribLocation(module_.gl_handle, location, name);
145 }
146 }
147
148 bool link() nothrow
149 {
150 foreach(ref module_;data.modules)
151 {
152 glLinkProgram(module_.gl_handle);
153
154 GLint ok = 0;
155 glGetProgramiv(module_.gl_handle, GL_LINK_STATUS, &ok);
156 if(!ok)
157 {
158 SDL_Log("Program link error!");
159 return false;
160 }
161 }
162
163 return true;
164 }
165
166 int getLocation(const char* name)
167 {
168 foreach(ref module_;data.modules)
169 {
170 int location = glGetUniformLocation(module_.gl_handle,name);
171 if(location != -1)return location;
172 }
173 return -1;
174 }
175
176 void pushBindings()
177 {
178 foreach(i;0..data.bindings.length)
179 {
180 glUniform1i(data.bindings[i],cast(int)i);
181 }
182 }
183
184 void pushUniforms(void* ptr)
185 {
186 foreach(ref Uniform uniform; data.uniforms)
187 {
188 void* local_ptr = ptr + uniform.offset;
189 glUniform4fv(uniform.location,1,cast(float*)local_ptr);
190 }
191 }
192
193 enum Type
194 {
195 float_,
196 float4
197 }
198
199 struct Uniform
200 {
201 Type type;
202 int location;
203 uint offset;
204 }
205
206 struct Data
207 {
208 BlendMode blend_mode = BlendMode.opaque;
209
210 ShaderModule[] modules;
211
212 TransformMode mode;
213
214 Uniform[] uniforms;
215 int[] bindings;
216 }
217
218 Data* data;
219 }