oculus2_psprite

annotate src/sdr.c @ 21:dc7af0f549b2

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