src/shader.c

changeset 160
80700db530ff
parent 158
f650994ec543
equal deleted inserted replaced
159:da7ebfcdd159 160:80700db530ff
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);

mercurial