src/shader.c

changeset 163
3628cc3c0483
parent 162
d3598c834f9b
equal deleted inserted replaced
162:d3598c834f9b 163:3628cc3c0483
97 } 97 }
98 98
99 /** 99 /**
100 * This function links shaders into a program. 100 * This function links shaders into a program.
101 * 101 *
102 * The ID of the returned program will be zero when something went wrong. 102 * The OpenGL ID of the program will be zero when something went wrong.
103 * 103 *
104 * @param shader the shader IDs to link 104 * @param shader the shader IDs to link
105 * @param n the number of shaders 105 * @param n the number of shaders
106 * @param prog the struct where to store the result 106 * @param prog the struct where to store the result
107 * @retval zero success
108 * @retval non-zero failure
109 */ 107 */
110 static int asc_shader_link(unsigned shader[], unsigned n, AscShaderProgram *prog) { 108 static void asc_shader_link(unsigned shader[], unsigned n, AscShaderProgram *prog) {
109 prog->gl_id = 0;
111 GLint success; 110 GLint success;
112 GLint id = glCreateProgram(); 111 GLint id = glCreateProgram();
113 if (id <= 0) { 112 if (id <= 0) {
113 for (unsigned i = 0; i < n; i++) {
114 asc_dprintf("Delete shader: %u", shader[i]);
115 glDeleteShader(shader[i]);
116 }
114 asc_error("glCreateProgram failed: %s", glGetError()); 117 asc_error("glCreateProgram failed: %s", glGetError());
115 return -1; 118 return;
116 } 119 }
117 for (unsigned i = 0; i < n; i++) { 120 for (unsigned i = 0; i < n; i++) {
118 glAttachShader(id, shader[i]); 121 glAttachShader(id, shader[i]);
119 } 122 }
120 glLinkProgram(id); 123 glLinkProgram(id);
121 glGetProgramiv(id, GL_LINK_STATUS, &success); 124 glGetProgramiv(id, GL_LINK_STATUS, &success);
122 for (unsigned i = 0; i < n; i++) { 125 for (unsigned i = 0; i < n; i++) {
126 asc_dprintf("Delete shader: %u", shader[i]);
123 glDeleteShader(shader[i]); 127 glDeleteShader(shader[i]);
124 } 128 }
125 if (success) { 129 if (success) {
126 asc_dprintf("Shader Program %u linked.", id); 130 asc_dprintf("Shader Program %u linked.", id);
127 prog->gl_id = id; 131 prog->gl_id = id;
128 // by convention every shader shall have MVP matrices 132 // by convention every shader shall have MVP matrices
129 prog->model = glGetUniformLocation(id, "model"); 133 prog->model = glGetUniformLocation(id, "model");
130 prog->view = glGetUniformLocation(id, "view"); 134 prog->view = glGetUniformLocation(id, "view");
131 prog->projection = glGetUniformLocation(id, "projection"); 135 prog->projection = glGetUniformLocation(id, "projection");
132 return 0;
133 } else { 136 } else {
134 char *log = malloc(1024); 137 char *log = malloc(1024);
135 glGetProgramInfoLog(id, 1024, NULL, log); 138 glGetProgramInfoLog(id, 1024, NULL, log);
136 glDeleteProgram(id); 139 glDeleteProgram(id);
137 asc_error("Linking shader program %u failed.\n%s", id, log); 140 asc_error("Linking shader program %u failed.\n%s", id, log);
138 free(log); 141 free(log);
139 return -1;
140 } 142 }
141 } 143 }
142 144
143 void asc_shader_free(AscShaderProgram *program) { 145 void asc_shader_free(AscShaderProgram *program) {
144 if (program->gl_id > 0) { 146 if (program->gl_id > 0) {
149 program->destr_func(program); 151 program->destr_func(program);
150 } 152 }
151 cxFreeDefault(program); 153 cxFreeDefault(program);
152 } 154 }
153 155
156 bool asc_shader_invalid(const AscShaderProgram *program) {
157 return program == NULL || program->gl_id == 0;
158 }
159
154 void *asc_shader_create(AscShaderCodes codes, size_t mem_size) { 160 void *asc_shader_create(AscShaderCodes codes, size_t mem_size) {
155 AscShaderProgram *prog = cxZallocDefault(mem_size); 161 AscShaderProgram *prog = cxZallocDefault(mem_size);
156 unsigned shader[2]; 162 unsigned shader[2];
157 unsigned n = 0; 163 unsigned n = 0;
158 bool shader_compile_error = false;
159 // TODO: clean up this pp mess by introducing proper nested structs 164 // TODO: clean up this pp mess by introducing proper nested structs
160 if (codes.vtx) { 165 if (codes.vtx) {
161 shader[n] = asc_shader_compile(GL_VERTEX_SHADER, codes.vtx, codes.vtx_pp, codes.vtx_pp_list, codes.vtx_pp_list_select); 166 shader[n++] = asc_shader_compile(GL_VERTEX_SHADER, codes.vtx, codes.vtx_pp, codes.vtx_pp_list, codes.vtx_pp_list_select);
162 shader_compile_error |= shader[n] == 0;
163 n++;
164 } 167 }
165 if (codes.frag) { 168 if (codes.frag) {
166 shader[n] = asc_shader_compile(GL_FRAGMENT_SHADER, codes.frag, codes.frag_pp, codes.frag_pp_list, codes.frag_pp_list_select); 169 shader[n++] = asc_shader_compile(GL_FRAGMENT_SHADER, codes.frag, codes.frag_pp, codes.frag_pp_list, codes.frag_pp_list_select);
167 shader_compile_error |= shader[n] == 0; 170 }
168 n++; 171 asc_shader_link(shader, n, prog);
169 }
170 if (shader_compile_error || asc_shader_link(shader, n, prog)) {
171 cxFreeDefault(prog);
172 prog = NULL;
173 }
174 for (unsigned i = 0; i < n; i++) {
175 if (shader[i] > 0) {
176 asc_dprintf("Delete shader: %u", shader[i]);
177 glDeleteShader(shader[i]);
178 }
179 }
180 return prog; 172 return prog;
181 } 173 }
182 174
183 void asc_shader_use(const AscShaderProgram *shader, const AscCamera *camera) { 175 void asc_shader_use(const AscShaderProgram *shader, const AscCamera *camera) {
184 if (shader == NULL) { 176 if (shader == NULL) {

mercurial