glviewvol

view src/sdr.c @ 12:773f89037a35

added copyright headers
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 31 Dec 2014 07:57:04 +0200
parents 04330eb80b36
children
line source
1 /*
2 glviewvol is an OpenGL 3D volume data viewer
3 Copyright (C) 2014 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <stdarg.h>
23 #include <assert.h>
24 #include <GL/glew.h>
26 #if defined(unix) || defined(__unix__)
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #endif /* unix */
31 #include "sdr.h"
33 static const char *sdrtypestr(unsigned int sdrtype);
35 unsigned int create_vertex_shader(const char *src)
36 {
37 return create_shader(src, GL_VERTEX_SHADER);
38 }
40 unsigned int create_pixel_shader(const char *src)
41 {
42 return create_shader(src, GL_FRAGMENT_SHADER);
43 }
45 unsigned int create_tessctl_shader(const char *src)
46 {
47 #ifdef GL_TESS_CONTROL_SHADER
48 return create_shader(src, GL_TESS_CONTROL_SHADER);
49 #else
50 return 0;
51 #endif
52 }
54 unsigned int create_tesseval_shader(const char *src)
55 {
56 #ifdef GL_TESS_EVALUATION_SHADER
57 return create_shader(src, GL_TESS_EVALUATION_SHADER);
58 #else
59 return 0;
60 #endif
61 }
63 unsigned int create_geometry_shader(const char *src)
64 {
65 #ifdef GL_GEOMETRY_SHADER
66 return create_shader(src, GL_GEOMETRY_SHADER);
67 #else
68 return 0;
69 #endif
70 }
72 unsigned int create_shader(const char *src, unsigned int sdr_type)
73 {
74 unsigned int sdr;
75 int success, info_len;
76 char *info_str = 0;
77 GLenum err;
79 sdr = glCreateShader(sdr_type);
80 assert(glGetError() == GL_NO_ERROR);
81 glShaderSource(sdr, 1, &src, 0);
82 err = glGetError();
83 assert(err == GL_NO_ERROR);
84 glCompileShader(sdr);
85 assert(glGetError() == GL_NO_ERROR);
87 glGetShaderiv(sdr, GL_COMPILE_STATUS, &success);
88 assert(glGetError() == GL_NO_ERROR);
89 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len);
90 assert(glGetError() == GL_NO_ERROR);
92 if(info_len) {
93 if((info_str = malloc(info_len + 1))) {
94 glGetShaderInfoLog(sdr, info_len, 0, info_str);
95 assert(glGetError() == GL_NO_ERROR);
96 info_str[info_len] = 0;
97 }
98 }
100 if(success) {
101 fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str);
102 } else {
103 fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str);
104 glDeleteShader(sdr);
105 sdr = 0;
106 }
108 free(info_str);
109 return sdr;
110 }
112 void free_shader(unsigned int sdr)
113 {
114 glDeleteShader(sdr);
115 }
117 unsigned int load_vertex_shader(const char *fname)
118 {
119 return load_shader(fname, GL_VERTEX_SHADER);
120 }
122 unsigned int load_pixel_shader(const char *fname)
123 {
124 return load_shader(fname, GL_FRAGMENT_SHADER);
125 }
127 unsigned int load_tessctl_shader(const char *fname)
128 {
129 #ifdef GL_TESS_CONTROL_SHADER
130 return load_shader(fname, GL_TESS_CONTROL_SHADER);
131 #else
132 return 0;
133 #endif
134 }
136 unsigned int load_tesseval_shader(const char *fname)
137 {
138 #ifdef GL_TESS_EVALUATION_SHADER
139 return load_shader(fname, GL_TESS_EVALUATION_SHADER);
140 #else
141 return 0;
142 #endif
143 }
145 unsigned int load_geometry_shader(const char *fname)
146 {
147 #ifdef GL_GEOMETRY_SHADER
148 return load_shader(fname, GL_GEOMETRY_SHADER);
149 #else
150 return 0;
151 #endif
152 }
154 unsigned int load_shader(const char *fname, unsigned int sdr_type)
155 {
156 #if defined(unix) || defined(__unix__)
157 struct stat st;
158 #endif
159 unsigned int sdr;
160 size_t filesize;
161 FILE *fp;
162 char *src;
164 if(!(fp = fopen(fname, "rb"))) {
165 fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno));
166 return 0;
167 }
169 #if defined(unix) || defined(__unix__)
170 fstat(fileno(fp), &st);
171 filesize = st.st_size;
172 #else
173 fseek(fp, 0, SEEK_END);
174 filesize = ftell(fp);
175 fseek(fp, 0, SEEK_SET);
176 #endif /* unix */
178 if(!(src = malloc(filesize + 1))) {
179 fclose(fp);
180 return 0;
181 }
182 fread(src, 1, filesize, fp);
183 src[filesize] = 0;
184 fclose(fp);
186 fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname);
187 sdr = create_shader(src, sdr_type);
189 free(src);
190 return sdr;
191 }
194 unsigned int get_vertex_shader(const char *fname)
195 {
196 return get_shader(fname, GL_VERTEX_SHADER);
197 }
199 unsigned int get_pixel_shader(const char *fname)
200 {
201 return get_shader(fname, GL_FRAGMENT_SHADER);
202 }
204 unsigned int get_tessctl_shader(const char *fname)
205 {
206 #ifdef GL_TESS_CONTROL_SHADER
207 return get_shader(fname, GL_TESS_CONTROL_SHADER);
208 #else
209 return 0;
210 #endif
211 }
213 unsigned int get_tesseval_shader(const char *fname)
214 {
215 #ifdef GL_TESS_EVALUATION_SHADER
216 return get_shader(fname, GL_TESS_EVALUATION_SHADER);
217 #else
218 return 0;
219 #endif
220 }
222 unsigned int get_geometry_shader(const char *fname)
223 {
224 #ifdef GL_GEOMETRY_SHADER
225 return get_shader(fname, GL_GEOMETRY_SHADER);
226 #else
227 return 0;
228 #endif
229 }
231 unsigned int get_shader(const char *fname, unsigned int sdr_type)
232 {
233 unsigned int sdr;
234 if(!(sdr = load_shader(fname, sdr_type))) {
235 return 0;
236 }
237 return sdr;
238 }
241 /* ---- gpu programs ---- */
243 unsigned int create_program(void)
244 {
245 unsigned int prog = glCreateProgram();
246 assert(glGetError() == GL_NO_ERROR);
247 return prog;
248 }
250 unsigned int create_program_link(unsigned int sdr0, ...)
251 {
252 unsigned int prog, sdr;
253 va_list ap;
255 if(!(prog = create_program())) {
256 return 0;
257 }
259 attach_shader(prog, sdr0);
260 if(glGetError()) {
261 return 0;
262 }
264 va_start(ap, sdr0);
265 while((sdr = va_arg(ap, unsigned int))) {
266 attach_shader(prog, sdr);
267 if(glGetError()) {
268 return 0;
269 }
270 }
271 va_end(ap);
273 if(link_program(prog) == -1) {
274 free_program(prog);
275 return 0;
276 }
277 return prog;
278 }
280 unsigned int create_program_load(const char *vfile, const char *pfile)
281 {
282 unsigned int vs = 0, ps = 0;
284 if(vfile && *vfile && !(vs = get_vertex_shader(vfile))) {
285 return 0;
286 }
287 if(pfile && *pfile && !(ps = get_pixel_shader(pfile))) {
288 return 0;
289 }
290 return create_program_link(vs, ps, 0);
291 }
293 void free_program(unsigned int sdr)
294 {
295 glDeleteProgram(sdr);
296 }
298 void attach_shader(unsigned int prog, unsigned int sdr)
299 {
300 if(prog && sdr) {
301 glAttachShader(prog, sdr);
302 assert(glGetError() == GL_NO_ERROR);
303 }
304 }
306 int link_program(unsigned int prog)
307 {
308 int linked, info_len, retval = 0;
309 char *info_str = 0;
311 glLinkProgram(prog);
312 assert(glGetError() == GL_NO_ERROR);
313 glGetProgramiv(prog, GL_LINK_STATUS, &linked);
314 assert(glGetError() == GL_NO_ERROR);
315 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len);
316 assert(glGetError() == GL_NO_ERROR);
318 if(info_len) {
319 if((info_str = malloc(info_len + 1))) {
320 glGetProgramInfoLog(prog, info_len, 0, info_str);
321 assert(glGetError() == GL_NO_ERROR);
322 info_str[info_len] = 0;
323 }
324 }
326 if(linked) {
327 fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str);
328 } else {
329 fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str);
330 retval = -1;
331 }
333 free(info_str);
334 return retval;
335 }
337 int bind_program(unsigned int prog)
338 {
339 GLenum err;
341 glUseProgram(prog);
342 if(prog && (err = glGetError()) != GL_NO_ERROR) {
343 /* maybe the program is not linked, try linking first */
344 if(err == GL_INVALID_OPERATION) {
345 if(link_program(prog) == -1) {
346 return -1;
347 }
348 glUseProgram(prog);
349 return glGetError() == GL_NO_ERROR ? 0 : -1;
350 }
351 return -1;
352 }
353 return 0;
354 }
356 /* ugly but I'm not going to write the same bloody code over and over */
357 #define BEGIN_UNIFORM_CODE \
358 int loc, curr_prog; \
359 glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \
360 if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \
361 return -1; \
362 } \
363 if((loc = glGetUniformLocation(prog, name)) != -1)
365 #define END_UNIFORM_CODE \
366 if((unsigned int)curr_prog != prog) { \
367 bind_program(curr_prog); \
368 } \
369 return loc == -1 ? -1 : 0
371 int set_uniform_int(unsigned int prog, const char *name, int val)
372 {
373 BEGIN_UNIFORM_CODE {
374 glUniform1i(loc, val);
375 }
376 END_UNIFORM_CODE;
377 }
379 int set_uniform_float(unsigned int prog, const char *name, float val)
380 {
381 BEGIN_UNIFORM_CODE {
382 glUniform1f(loc, val);
383 }
384 END_UNIFORM_CODE;
385 }
387 int set_uniform_float2(unsigned int prog, const char *name, float x, float y)
388 {
389 BEGIN_UNIFORM_CODE {
390 glUniform2f(loc, x, y);
391 }
392 END_UNIFORM_CODE;
393 }
395 int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z)
396 {
397 BEGIN_UNIFORM_CODE {
398 glUniform3f(loc, x, y, z);
399 }
400 END_UNIFORM_CODE;
401 }
403 int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w)
404 {
405 BEGIN_UNIFORM_CODE {
406 glUniform4f(loc, x, y, z, w);
407 }
408 END_UNIFORM_CODE;
409 }
411 int set_uniform_matrix4(unsigned int prog, const char *name, float *mat)
412 {
413 BEGIN_UNIFORM_CODE {
414 glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
415 }
416 END_UNIFORM_CODE;
417 }
419 int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat)
420 {
421 BEGIN_UNIFORM_CODE {
422 glUniformMatrix4fv(loc, 1, GL_TRUE, mat);
423 }
424 END_UNIFORM_CODE;
425 }
427 int get_attrib_loc(unsigned int prog, const char *name)
428 {
429 int loc, curr_prog;
431 glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog);
432 if((unsigned int)curr_prog != prog && bind_program(prog) == -1) {
433 return -1;
434 }
436 loc = glGetAttribLocation(prog, (char*)name);
438 if((unsigned int)curr_prog != prog) {
439 bind_program(curr_prog);
440 }
441 return loc;
442 }
444 void set_attrib_float3(int attr_loc, float x, float y, float z)
445 {
446 glVertexAttrib3f(attr_loc, x, y, z);
447 }
449 static const char *sdrtypestr(unsigned int sdrtype)
450 {
451 switch(sdrtype) {
452 case GL_VERTEX_SHADER:
453 return "vertex";
454 case GL_FRAGMENT_SHADER:
455 return "pixel";
456 #ifdef GL_TESS_CONTROL_SHADER
457 case GL_TESS_CONTROL_SHADER:
458 return "tessellation control";
459 #endif
460 #ifdef GL_TESS_EVALUATION_SHADER
461 case GL_TESS_EVALUATION_SHADER:
462 return "tessellation evaluation";
463 #endif
464 #ifdef GL_GEOMETRY_SHADER
465 case GL_GEOMETRY_SHADER:
466 return "geometry";
467 #endif
469 default:
470 break;
471 }
472 return "<unknown>";
473 }