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 }