42 * The ID of the returned shader will be zero when something went wrong. |
42 * The ID of the returned shader will be zero when something went wrong. |
43 * |
43 * |
44 * @param type the shader type (use the GL enum) |
44 * @param type the shader type (use the GL enum) |
45 * @param code the source code |
45 * @param code the source code |
46 * @param code_pp the optional preprocessor code |
46 * @param code_pp the optional preprocessor code |
|
47 * @param code_pp_list list of optional preprocessor code |
|
48 * @param code_pp_list_select selection flags for the preprocessor code list |
47 * @return the compiled shader |
49 * @return the compiled shader |
48 */ |
50 */ |
49 static unsigned asc_shader_compile(unsigned int type, const char *code, const char *code_pp) { |
51 static unsigned asc_shader_compile(unsigned int type, const char *code, const char *code_pp, |
|
52 const char * const *code_pp_list, unsigned short code_pp_list_select) { |
50 GLuint id = glCreateShader(type); |
53 GLuint id = glCreateShader(type); |
51 if (id == 0) { |
54 if (id == 0) { |
52 asc_error("glCreateShader failed: %s", glGetError()); |
55 asc_error("glCreateShader failed: %s", glGetError()); |
53 return 0; |
56 return 0; |
54 } |
57 } |
55 |
58 |
56 // some drivers don't like NULL strings, even when length is zero |
|
57 if (code_pp == NULL) code_pp = ""; |
|
58 |
|
59 GLint success; |
59 GLint success; |
60 const char *code_array[4] = { |
60 const char *code_array[20]; |
61 "#version 400 core\n", |
61 GLsizei code_count = 0; |
62 code_pp, |
62 code_array[code_count++] = "#version 400 core\n"; |
63 "\n#line 1\n", |
63 if (code_pp != NULL) code_array[code_count++] = code_pp; |
64 code |
64 unsigned test_flag = 1; |
65 }; |
65 unsigned select_index = 0; |
66 GLint length_array[4]; |
66 while (test_flag <= code_pp_list_select) { |
67 for (unsigned int i = 0; i < cx_nmemb(length_array); i++) { |
67 if (asc_test_flag(code_pp_list_select, test_flag)) { |
|
68 code_array[code_count++] = code_pp_list[select_index]; |
|
69 } |
|
70 select_index++; |
|
71 test_flag <<= 1; |
|
72 } |
|
73 code_array[code_count++] = "\n#line 1\n"; |
|
74 code_array[code_count++] = code; |
|
75 |
|
76 // compute the lengths |
|
77 GLint length_array[20]; |
|
78 for (int i = 0; i < code_count ; i++) { |
68 length_array[i] = (GLint) strlen(code_array[i]); |
79 length_array[i] = (GLint) strlen(code_array[i]); |
69 } |
80 } |
70 |
81 |
71 // compile |
82 // compile |
72 glShaderSource(id, cx_nmemb(length_array), code_array, length_array); |
83 glShaderSource(id, code_count, code_array, length_array); |
73 glCompileShader(id); |
84 glCompileShader(id); |
74 glGetShaderiv(id, GL_COMPILE_STATUS, &success); |
85 glGetShaderiv(id, GL_COMPILE_STATUS, &success); |
75 if (success) { |
86 if (success) { |
76 asc_dprintf("Shader %u compiled", id); |
87 asc_dprintf("Shader %u compiled", id); |
77 return id; |
88 return id; |
143 void *asc_shader_create(AscShaderCodes codes, size_t mem_size) { |
154 void *asc_shader_create(AscShaderCodes codes, size_t mem_size) { |
144 AscShaderProgram *prog = cxZallocDefault(mem_size); |
155 AscShaderProgram *prog = cxZallocDefault(mem_size); |
145 unsigned shader[2]; |
156 unsigned shader[2]; |
146 unsigned n = 0; |
157 unsigned n = 0; |
147 if (codes.vtx) { |
158 if (codes.vtx) { |
148 shader[n++] = asc_shader_compile(GL_VERTEX_SHADER, codes.vtx, codes.vtx_pp); |
159 shader[n++] = asc_shader_compile(GL_VERTEX_SHADER, codes.vtx, codes.vtx_pp, codes.vtx_pp_list, codes.vtx_pp_list_select); |
149 } |
160 } |
150 if (codes.frag) { |
161 if (codes.frag) { |
151 shader[n++] = asc_shader_compile(GL_FRAGMENT_SHADER, codes.frag, codes.frag_pp); |
162 shader[n++] = asc_shader_compile(GL_FRAGMENT_SHADER, codes.frag, codes.frag_pp, codes.frag_pp_list, codes.frag_pp_list_select); |
152 } |
163 } |
153 if (asc_shader_link(shader, n, prog)) { |
164 if (asc_shader_link(shader, n, prog)) { |
154 cxFreeDefault(prog); |
165 cxFreeDefault(prog); |
155 prog = NULL; |
166 prog = NULL; |
156 } |
167 } |
195 |
206 |
196 int asc_shader_load_code_files(AscShaderCodeInfo info, AscShaderCodes *codes) { |
207 int asc_shader_load_code_files(AscShaderCodeInfo info, AscShaderCodes *codes) { |
197 int ret = 0; |
208 int ret = 0; |
198 ret |= asc_shader_load_code_file(info.files.vtx, &codes->vtx); |
209 ret |= asc_shader_load_code_file(info.files.vtx, &codes->vtx); |
199 codes->vtx_pp = info.defines.vtx; |
210 codes->vtx_pp = info.defines.vtx; |
|
211 codes->vtx_pp_list = info.defines.vtx_list; |
|
212 codes->vtx_pp_list_select = info.defines.vtx_list_select; |
200 ret |= asc_shader_load_code_file(info.files.frag, &codes->frag); |
213 ret |= asc_shader_load_code_file(info.files.frag, &codes->frag); |
201 codes->frag_pp = info.defines.frag; |
214 codes->frag_pp = info.defines.frag; |
|
215 codes->frag_pp_list = info.defines.frag_list; |
|
216 codes->frag_pp_list_select = info.defines.frag_list_select; |
202 return ret; |
217 return ret; |
203 } |
218 } |
204 |
219 |
205 void asc_shader_free_codes(AscShaderCodes codes) { |
220 void asc_shader_free_codes(AscShaderCodes codes) { |
206 cxFreeDefault(codes.vtx); |
221 cxFreeDefault(codes.vtx); |