155 } |
155 } |
156 return prog; |
156 return prog; |
157 } |
157 } |
158 |
158 |
159 void asc_shader_use(const AscShaderProgram *shader, const AscCamera *camera) { |
159 void asc_shader_use(const AscShaderProgram *shader, const AscCamera *camera) { |
|
160 if (shader == NULL) { |
|
161 asc_active_glctx->active_program = 0; |
|
162 glUseProgram(0); |
|
163 return; |
|
164 } |
|
165 if (asc_active_glctx->active_program == shader->gl_id) return; |
|
166 asc_active_glctx->active_program = shader->gl_id; |
160 glUseProgram(shader->gl_id); |
167 glUseProgram(shader->gl_id); |
161 glUniformMatrix4fv(shader->projection, 1, GL_FALSE, camera->projection); |
168 glUniformMatrix4fv(shader->projection, 1, GL_FALSE, camera->projection); |
162 glUniformMatrix4fv(shader->view, 1, GL_FALSE, camera->view); |
169 glUniformMatrix4fv(shader->view, 1, GL_FALSE, camera->view); |
163 } |
170 } |
164 |
171 |
193 void asc_shader_free_codes(AscShaderCodes codes) { |
200 void asc_shader_free_codes(AscShaderCodes codes) { |
194 cxFreeDefault(codes.vtx); |
201 cxFreeDefault(codes.vtx); |
195 cxFreeDefault(codes.frag); |
202 cxFreeDefault(codes.frag); |
196 } |
203 } |
197 |
204 |
198 AscShaderProgram *asc_shader_register(unsigned int id, asc_shader_create_func create_func) { |
205 const void *asc_shader_register(unsigned int id, asc_shader_create_func create_func) { |
199 AscGLContext *glctx = asc_active_glctx; |
206 AscGLContext *glctx = asc_active_glctx; |
200 AscShaderProgram *prog = NULL; |
|
201 #ifndef NDEBUG |
207 #ifndef NDEBUG |
202 prog = asc_shader_lookup(id); |
208 { |
203 if (prog != NULL) { |
209 const AscShaderProgram *prog = asc_shader_lookup(id); |
204 asc_error("Shader program %u already exists. This is a bug!", id); |
210 if (prog != NULL) { |
205 // still return it, so that the caller does not die immediately |
211 asc_error("Shader program %u already exists. This is a bug!", id); |
206 return prog; |
212 // still return it, so that the caller does not die immediately |
|
213 return prog; |
|
214 } |
207 } |
215 } |
208 #endif |
216 #endif |
209 prog = create_func(); |
217 AscShaderProgram *prog = create_func(); |
210 prog->id = id; |
218 prog->id = id; |
211 cxListAdd(glctx->shaders, prog); |
219 cxListAdd(glctx->shaders, prog); |
212 return prog; |
220 return prog; |
213 } |
221 } |
214 |
222 |
215 AscShaderProgram *asc_shader_lookup(unsigned int id) { |
223 const void *asc_shader_lookup(unsigned int id) { |
216 CxIterator iter = cxListIterator(asc_active_glctx->shaders); |
224 CxIterator iter = cxListIterator(asc_active_glctx->shaders); |
217 cx_foreach(AscShaderProgram *, prog, iter) { |
225 cx_foreach(const AscShaderProgram *, prog, iter) { |
218 if (prog->id == id) return prog; |
226 if (prog->id == id) return prog; |
219 } |
227 } |
220 return NULL; |
228 return NULL; |
221 } |
229 } |
222 |
230 |
223 AscShaderProgram *asc_shader_lookup_or_create(unsigned int id, asc_shader_create_func create_func) { |
231 const void *asc_shader_lookup_or_create(unsigned int id, asc_shader_create_func create_func) { |
224 AscShaderProgram *prog = asc_shader_lookup(id); |
232 const AscShaderProgram *prog = asc_shader_lookup(id); |
225 if (prog == NULL) { |
233 if (prog == NULL) { |
226 return asc_shader_register(id, create_func); |
234 return asc_shader_register(id, create_func); |
227 } |
235 } |
228 return prog; |
236 return prog; |
229 } |
237 } |
230 |
238 |
231 void asc_shader_clear_registry(void) { |
239 void asc_shader_clear_registry(void) { |
232 cxListClear(asc_active_glctx->shaders); |
240 cxListClear(asc_active_glctx->shaders); |
233 } |
241 // also clear the active program to avoid accidental matches with newly created shaders |
|
242 asc_shader_use(NULL, NULL); |
|
243 } |