coeng

annotate src/shader.cc @ 8:8cce82794f90

seems to work nicely
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 15 Feb 2015 05:14:20 +0200
parents
children
rev   line source
nuclear@8 1 #include <stdio.h>
nuclear@8 2 #include <string.h>
nuclear@8 3 #include <stdarg.h>
nuclear@8 4 #include <errno.h>
nuclear@8 5 #include "opengl.h"
nuclear@8 6 #include "shader.h"
nuclear@8 7 #include "mesh.h"
nuclear@8 8
nuclear@8 9 #ifdef _MSC_VER
nuclear@8 10 #include <malloc.h>
nuclear@8 11 #else
nuclear@8 12 #include <alloca.h>
nuclear@8 13 #endif
nuclear@8 14
nuclear@8 15 #ifdef __GLEW_H__
nuclear@8 16 #define HAVE_GEOMETRY_SHADER
nuclear@8 17 #define HAVE_TESSELATION_SHADER
nuclear@8 18 #endif
nuclear@8 19
nuclear@8 20 static std::string read_source(const char *fname);
nuclear@8 21 static void bind_standard_attr(const ShaderProg *prog);
nuclear@8 22
nuclear@8 23 ShaderProg *ShaderProg::current;
nuclear@8 24
nuclear@8 25 void bind_shader(const ShaderProg *sdr)
nuclear@8 26 {
nuclear@8 27 if(sdr) {
nuclear@8 28 sdr->bind();
nuclear@8 29 } else {
nuclear@8 30 #ifndef GL_ES_VERSION_2_0
nuclear@8 31 glUseProgram(0);
nuclear@8 32 ShaderProg::current = 0;
nuclear@8 33 #endif
nuclear@8 34 }
nuclear@8 35 }
nuclear@8 36
nuclear@8 37 const ShaderProg *get_current_shader()
nuclear@8 38 {
nuclear@8 39 return ShaderProg::current;
nuclear@8 40 }
nuclear@8 41
nuclear@8 42 Shader::Shader()
nuclear@8 43 {
nuclear@8 44 sdr = type = 0;
nuclear@8 45 }
nuclear@8 46
nuclear@8 47 Shader::~Shader()
nuclear@8 48 {
nuclear@8 49 destroy();
nuclear@8 50 }
nuclear@8 51
nuclear@8 52 unsigned int Shader::get_id() const
nuclear@8 53 {
nuclear@8 54 return sdr;
nuclear@8 55 }
nuclear@8 56
nuclear@8 57 void Shader::set_name(const char *name)
nuclear@8 58 {
nuclear@8 59 this->name = std::string(name);
nuclear@8 60 }
nuclear@8 61
nuclear@8 62 const char *Shader::get_name() const
nuclear@8 63 {
nuclear@8 64 return name.c_str();
nuclear@8 65 }
nuclear@8 66
nuclear@8 67 bool Shader::create(const char *src, unsigned int type)
nuclear@8 68 {
nuclear@8 69 #if !GL_ES_VERSION_2_0
nuclear@8 70 const char *src_arr[] = {src};
nuclear@8 71 #else
nuclear@8 72 const char *src_arr[] = { "precision mediump float; ", src };
nuclear@8 73 #endif
nuclear@8 74
nuclear@8 75 // keep a copy of the source code
nuclear@8 76 this->src = std::string(src);
nuclear@8 77
nuclear@8 78 if(!sdr) {
nuclear@8 79 sdr = glCreateShader(type);
nuclear@8 80 }
nuclear@8 81
nuclear@8 82 printf("compiling shader: %s... ", name.c_str());
nuclear@8 83
nuclear@8 84 glShaderSource(sdr, sizeof src_arr / sizeof *src_arr, src_arr, 0);
nuclear@8 85 glCompileShader(sdr);
nuclear@8 86
nuclear@8 87 int status;
nuclear@8 88 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
nuclear@8 89
nuclear@8 90 printf(status ? "success\n" : "failed\n");
nuclear@8 91
nuclear@8 92 int info_len;
nuclear@8 93 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len);
nuclear@8 94 if(info_len > 1) {
nuclear@8 95 char *buf = (char*)alloca(info_len);
nuclear@8 96 glGetShaderInfoLog(sdr, info_len, 0, buf);
nuclear@8 97 buf[info_len - 1] = 0;
nuclear@8 98
nuclear@8 99 if(status) {
nuclear@8 100 printf("%s\n", buf);
nuclear@8 101 } else {
nuclear@8 102 fprintf(stderr, "%s\n", buf);
nuclear@8 103 }
nuclear@8 104 }
nuclear@8 105
nuclear@8 106 return status == GL_TRUE;
nuclear@8 107 }
nuclear@8 108
nuclear@8 109 void Shader::destroy()
nuclear@8 110 {
nuclear@8 111 if(sdr) {
nuclear@8 112 glDeleteShader(sdr);
nuclear@8 113 }
nuclear@8 114 sdr = type = 0;
nuclear@8 115
nuclear@8 116 src.clear();
nuclear@8 117 name.clear();
nuclear@8 118 }
nuclear@8 119
nuclear@8 120 static std::string read_source(const char *fname)
nuclear@8 121 {
nuclear@8 122 FILE *fp;
nuclear@8 123
nuclear@8 124 if(!(fp = fopen(fname, "rb"))) {
nuclear@8 125 fprintf(stderr, "failed to load shader: %s: %s\n", fname, strerror(errno));
nuclear@8 126 return std::string();
nuclear@8 127 }
nuclear@8 128
nuclear@8 129 fseek(fp, 0, SEEK_END);
nuclear@8 130 long sz = ftell(fp);
nuclear@8 131 rewind(fp);
nuclear@8 132
nuclear@8 133 char *src = (char*)alloca(sz + 1);
nuclear@8 134 if(fread(src, 1, sz, fp) < (size_t)sz) {
nuclear@8 135 fprintf(stderr, "failed to load shader: %s: %s\n", fname, strerror(errno));
nuclear@8 136 fclose(fp);
nuclear@8 137 delete [] src;
nuclear@8 138 return std::string();
nuclear@8 139 }
nuclear@8 140 src[sz] = 0;
nuclear@8 141 fclose(fp);
nuclear@8 142
nuclear@8 143 return std::string(src);
nuclear@8 144 }
nuclear@8 145
nuclear@8 146 bool Shader::load(const char *fname, unsigned int type)
nuclear@8 147 {
nuclear@8 148 std::string src = read_source(fname);
nuclear@8 149 if(src.empty()) {
nuclear@8 150 return false;
nuclear@8 151 }
nuclear@8 152 set_name(fname);
nuclear@8 153 return create(src.c_str(), type);
nuclear@8 154 }
nuclear@8 155
nuclear@8 156 // ---- shader program ----
nuclear@8 157 ShaderProg::ShaderProg()
nuclear@8 158 {
nuclear@8 159 prog = 0;
nuclear@8 160 must_link = true;
nuclear@8 161 }
nuclear@8 162
nuclear@8 163 ShaderProg::~ShaderProg()
nuclear@8 164 {
nuclear@8 165 destroy();
nuclear@8 166 }
nuclear@8 167
nuclear@8 168 unsigned int ShaderProg::get_id() const
nuclear@8 169 {
nuclear@8 170 return prog;
nuclear@8 171 }
nuclear@8 172
nuclear@8 173 bool ShaderProg::create(const char *src, unsigned int type, ...)
nuclear@8 174 {
nuclear@8 175 va_list ap;
nuclear@8 176
nuclear@8 177 va_start(ap, type);
nuclear@8 178 bool res = create(src, type, ap);
nuclear@8 179 va_end(ap);
nuclear@8 180
nuclear@8 181 return res;
nuclear@8 182 }
nuclear@8 183
nuclear@8 184 bool ShaderProg::create(const char *src, unsigned int type, va_list ap)
nuclear@8 185 {
nuclear@8 186 destroy();
nuclear@8 187 prog = glCreateProgram();
nuclear@8 188
nuclear@8 189 while(src) {
nuclear@8 190 Shader *sdr = new Shader;
nuclear@8 191 if(!sdr->create(src, type)) {
nuclear@8 192 va_end(ap);
nuclear@8 193 return false;
nuclear@8 194 }
nuclear@8 195 add_shader(sdr);
nuclear@8 196 src = va_arg(ap, const char*);
nuclear@8 197 type = va_arg(ap, unsigned int);
nuclear@8 198 }
nuclear@8 199
nuclear@8 200 return link();
nuclear@8 201 }
nuclear@8 202
nuclear@8 203 bool ShaderProg::create(const char *vsrc, const char *psrc)
nuclear@8 204 {
nuclear@8 205 return create(VSDR(vsrc), PSDR(psrc), 0);
nuclear@8 206 }
nuclear@8 207
nuclear@8 208 bool ShaderProg::create(Shader *sdr, ...)
nuclear@8 209 {
nuclear@8 210 va_list ap;
nuclear@8 211
nuclear@8 212 va_start(ap, sdr);
nuclear@8 213 bool res = create(sdr, ap);
nuclear@8 214 va_end(ap);
nuclear@8 215
nuclear@8 216 return res;
nuclear@8 217 }
nuclear@8 218
nuclear@8 219 bool ShaderProg::create(Shader *sdr, va_list ap)
nuclear@8 220 {
nuclear@8 221 destroy();
nuclear@8 222 prog = glCreateProgram();
nuclear@8 223
nuclear@8 224 while(sdr) {
nuclear@8 225 add_shader(sdr);
nuclear@8 226 sdr = va_arg(ap, Shader*);
nuclear@8 227 }
nuclear@8 228 return link();
nuclear@8 229 }
nuclear@8 230
nuclear@8 231 bool ShaderProg::create(Shader *vsdr, Shader *psdr)
nuclear@8 232 {
nuclear@8 233 return create(vsdr, psdr, 0);
nuclear@8 234 }
nuclear@8 235
nuclear@8 236 void ShaderProg::destroy()
nuclear@8 237 {
nuclear@8 238 if(prog) {
nuclear@8 239 glDeleteProgram(prog);
nuclear@8 240 }
nuclear@8 241 prog = 0;
nuclear@8 242
nuclear@8 243 shaders.clear();
nuclear@8 244 // don't actually destroy the shaders, let the ShaderSet own them
nuclear@8 245 }
nuclear@8 246
nuclear@8 247 bool ShaderProg::load(const char *fname, unsigned int type, ...)
nuclear@8 248 {
nuclear@8 249 va_list ap;
nuclear@8 250 va_start(ap, type);
nuclear@8 251 bool res = load(fname, type, ap);
nuclear@8 252 va_end(ap);
nuclear@8 253
nuclear@8 254 return res;
nuclear@8 255 }
nuclear@8 256
nuclear@8 257 bool ShaderProg::load(const char *fname, unsigned int type, va_list ap)
nuclear@8 258 {
nuclear@8 259 destroy();
nuclear@8 260 prog = glCreateProgram();
nuclear@8 261
nuclear@8 262 while(fname) {
nuclear@8 263 Shader *sdr = new Shader;
nuclear@8 264 if(!sdr->load(fname, type)) {
nuclear@8 265 delete sdr;
nuclear@8 266 return false;
nuclear@8 267 }
nuclear@8 268 add_shader(sdr);
nuclear@8 269
nuclear@8 270 if((fname = va_arg(ap, const char*))) {
nuclear@8 271 type = va_arg(ap, unsigned int);
nuclear@8 272 }
nuclear@8 273 }
nuclear@8 274
nuclear@8 275 return link();
nuclear@8 276 }
nuclear@8 277
nuclear@8 278 bool ShaderProg::load(const char *vfname, const char *pfname)
nuclear@8 279 {
nuclear@8 280 return load(VSDR(vfname), PSDR(pfname), 0);
nuclear@8 281 }
nuclear@8 282
nuclear@8 283 void ShaderProg::add_shader(Shader *sdr)
nuclear@8 284 {
nuclear@8 285 glAttachShader(prog, sdr->get_id());
nuclear@8 286 }
nuclear@8 287
nuclear@8 288 bool ShaderProg::link() const
nuclear@8 289 {
nuclear@8 290 bind_standard_attr(this);
nuclear@8 291
nuclear@8 292 printf("linking program ... ");
nuclear@8 293 glLinkProgram(prog);
nuclear@8 294
nuclear@8 295 int status;
nuclear@8 296 glGetProgramiv(prog, GL_LINK_STATUS, &status);
nuclear@8 297
nuclear@8 298 printf(status ? "success\n" : "failed\n");
nuclear@8 299
nuclear@8 300 int info_len;
nuclear@8 301 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len);
nuclear@8 302 if(info_len > 1) {
nuclear@8 303 char *buf = (char*)alloca(info_len);
nuclear@8 304 glGetProgramInfoLog(prog, info_len, 0, buf);
nuclear@8 305 buf[info_len - 1] = 0;
nuclear@8 306
nuclear@8 307 if(status) {
nuclear@8 308 printf("%s\n", buf);
nuclear@8 309 } else {
nuclear@8 310 fprintf(stderr, "%s\n", buf);
nuclear@8 311 }
nuclear@8 312 }
nuclear@8 313
nuclear@8 314 if(status) {
nuclear@8 315 must_link = false;
nuclear@8 316 //cache_state_uniforms();
nuclear@8 317 return true;
nuclear@8 318 }
nuclear@8 319 return false;
nuclear@8 320 }
nuclear@8 321
nuclear@8 322 void ShaderProg::bind() const
nuclear@8 323 {
nuclear@8 324 if(must_link) {
nuclear@8 325 if(!link()) {
nuclear@8 326 return;
nuclear@8 327 }
nuclear@8 328 }
nuclear@8 329 glUseProgram(prog);
nuclear@8 330 ShaderProg::current = (ShaderProg*)this;
nuclear@8 331
nuclear@8 332 //setup_state_uniforms();
nuclear@8 333 }
nuclear@8 334
nuclear@8 335
nuclear@8 336 int ShaderProg::get_attrib_location(const char *name) const
nuclear@8 337 {
nuclear@8 338 glUseProgram(prog);
nuclear@8 339 return glGetAttribLocation(prog, name);
nuclear@8 340 }
nuclear@8 341
nuclear@8 342 void ShaderProg::set_attrib_location(const char *name, int loc) const
nuclear@8 343 {
nuclear@8 344 glBindAttribLocation(prog, loc, name);
nuclear@8 345 must_link = true;
nuclear@8 346 }
nuclear@8 347
nuclear@8 348 int ShaderProg::get_uniform_location(const char *name) const
nuclear@8 349 {
nuclear@8 350 glUseProgram(prog);
nuclear@8 351 return glGetUniformLocation(prog, name);
nuclear@8 352 }
nuclear@8 353
nuclear@8 354 bool ShaderProg::set_uniform(int loc, int val) const
nuclear@8 355 {
nuclear@8 356 glUseProgram(prog);
nuclear@8 357 if(loc >= 0) {
nuclear@8 358 glUniform1i(loc, val);
nuclear@8 359 return true;
nuclear@8 360 }
nuclear@8 361 return false;
nuclear@8 362 }
nuclear@8 363
nuclear@8 364 bool ShaderProg::set_uniform(int loc, float val) const
nuclear@8 365 {
nuclear@8 366 glUseProgram(prog);
nuclear@8 367 if(loc >= 0) {
nuclear@8 368 glUniform1f(loc, val);
nuclear@8 369 return true;
nuclear@8 370 }
nuclear@8 371 return false;
nuclear@8 372 }
nuclear@8 373
nuclear@8 374 bool ShaderProg::set_uniform(int loc, const Vector2 &v) const
nuclear@8 375 {
nuclear@8 376 glUseProgram(prog);
nuclear@8 377 if(loc >= 0) {
nuclear@8 378 glUniform2f(loc, v.x, v.y);
nuclear@8 379 return true;
nuclear@8 380 }
nuclear@8 381 return false;
nuclear@8 382 }
nuclear@8 383
nuclear@8 384 bool ShaderProg::set_uniform(int loc, const Vector3 &v) const
nuclear@8 385 {
nuclear@8 386 glUseProgram(prog);
nuclear@8 387 if(loc >= 0) {
nuclear@8 388 glUniform3f(loc, v.x, v.y, v.z);
nuclear@8 389 return true;
nuclear@8 390 }
nuclear@8 391 return false;
nuclear@8 392 }
nuclear@8 393
nuclear@8 394 bool ShaderProg::set_uniform(int loc, const Vector4 &v) const
nuclear@8 395 {
nuclear@8 396 glUseProgram(prog);
nuclear@8 397 if(loc >= 0) {
nuclear@8 398 glUniform4f(loc, v.x, v.y, v.z, v.w);
nuclear@8 399 return true;
nuclear@8 400 }
nuclear@8 401 return false;
nuclear@8 402 }
nuclear@8 403
nuclear@8 404 bool ShaderProg::set_uniform(int loc, const Matrix3x3 &m) const
nuclear@8 405 {
nuclear@8 406 glUseProgram(prog);
nuclear@8 407 if(loc >= 0) {
nuclear@8 408 glUniformMatrix3fv(loc, 1, GL_TRUE, m[0]);
nuclear@8 409 return true;
nuclear@8 410 }
nuclear@8 411 return false;
nuclear@8 412 }
nuclear@8 413
nuclear@8 414 bool ShaderProg::set_uniform(int loc, const Matrix4x4 &m) const
nuclear@8 415 {
nuclear@8 416 glUseProgram(prog);
nuclear@8 417 if(loc >= 0) {
nuclear@8 418 glUniformMatrix4fv(loc, 1, GL_TRUE, m[0]);
nuclear@8 419 return true;
nuclear@8 420 }
nuclear@8 421 return false;
nuclear@8 422 }
nuclear@8 423
nuclear@8 424
nuclear@8 425 bool ShaderProg::set_uniform(const char *name, int val) const
nuclear@8 426 {
nuclear@8 427 return set_uniform(get_uniform_location(name), val);
nuclear@8 428 }
nuclear@8 429
nuclear@8 430 bool ShaderProg::set_uniform(const char *name, float val) const
nuclear@8 431 {
nuclear@8 432 return set_uniform(get_uniform_location(name), val);
nuclear@8 433 }
nuclear@8 434
nuclear@8 435 bool ShaderProg::set_uniform(const char *name, const Vector2 &v) const
nuclear@8 436 {
nuclear@8 437 return set_uniform(get_uniform_location(name), v);
nuclear@8 438 }
nuclear@8 439
nuclear@8 440 bool ShaderProg::set_uniform(const char *name, const Vector3 &v) const
nuclear@8 441 {
nuclear@8 442 return set_uniform(get_uniform_location(name), v);
nuclear@8 443 }
nuclear@8 444
nuclear@8 445 bool ShaderProg::set_uniform(const char *name, const Vector4 &v) const
nuclear@8 446 {
nuclear@8 447 return set_uniform(get_uniform_location(name), v);
nuclear@8 448 }
nuclear@8 449
nuclear@8 450 bool ShaderProg::set_uniform(const char *name, const Matrix3x3 &m) const
nuclear@8 451 {
nuclear@8 452 return set_uniform(get_uniform_location(name), m);
nuclear@8 453 }
nuclear@8 454
nuclear@8 455 bool ShaderProg::set_uniform(const char *name, const Matrix4x4 &m) const
nuclear@8 456 {
nuclear@8 457 return set_uniform(get_uniform_location(name), m);
nuclear@8 458 }
nuclear@8 459
nuclear@8 460 /*
nuclear@8 461 static StType unist_type(GLenum type)
nuclear@8 462 {
nuclear@8 463 switch(type) {
nuclear@8 464 case GL_FLOAT:
nuclear@8 465 return ST_FLOAT;
nuclear@8 466 case GL_FLOAT_VEC2:
nuclear@8 467 return ST_FLOAT2;
nuclear@8 468 case GL_FLOAT_VEC3:
nuclear@8 469 return ST_FLOAT3;
nuclear@8 470 case GL_FLOAT_VEC4:
nuclear@8 471 return ST_FLOAT4;
nuclear@8 472 case GL_INT:
nuclear@8 473 case GL_SAMPLER_2D:
nuclear@8 474 case GL_SAMPLER_CUBE:
nuclear@8 475 #if !GL_ES_VERSION_2_0
nuclear@8 476 case GL_SAMPLER_1D:
nuclear@8 477 case GL_SAMPLER_3D:
nuclear@8 478 case GL_SAMPLER_1D_SHADOW:
nuclear@8 479 case GL_SAMPLER_2D_SHADOW:
nuclear@8 480 #endif
nuclear@8 481 return ST_INT;
nuclear@8 482 case GL_INT_VEC2:
nuclear@8 483 return ST_INT2;
nuclear@8 484 case GL_INT_VEC3:
nuclear@8 485 return ST_INT3;
nuclear@8 486 case GL_INT_VEC4:
nuclear@8 487 return ST_INT4;
nuclear@8 488 case GL_FLOAT_MAT3:
nuclear@8 489 return ST_MATRIX3;
nuclear@8 490 case GL_FLOAT_MAT4:
nuclear@8 491 return ST_MATRIX4;
nuclear@8 492 default:
nuclear@8 493 break;
nuclear@8 494 }
nuclear@8 495 return ST_UNKNOWN;
nuclear@8 496 }
nuclear@8 497
nuclear@8 498 void ShaderProg::cache_state_uniforms() const
nuclear@8 499 {
nuclear@8 500 if(!glIsProgram(prog)) {
nuclear@8 501 return;
nuclear@8 502 }
nuclear@8 503
nuclear@8 504 int num_uni;
nuclear@8 505 glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_uni);
nuclear@8 506
nuclear@8 507 char name[256];
nuclear@8 508 for(int i=0; i<num_uni; i++) {
nuclear@8 509 GLint sz;
nuclear@8 510 GLenum type;
nuclear@8 511 glGetActiveUniform(prog, i, sizeof name - 1, 0, &sz, &type, name);
nuclear@8 512
nuclear@8 513 if(strstr(name, "st_") == name) {
nuclear@8 514 StateLocCache s;
nuclear@8 515 s.sidx = add_unistate(name, unist_type(type));
nuclear@8 516 s.loc = glGetUniformLocation(prog, name);
nuclear@8 517 stloc_cache.push_back(s);
nuclear@8 518 }
nuclear@8 519 }
nuclear@8 520 }
nuclear@8 521
nuclear@8 522 void ShaderProg::setup_state_uniforms() const
nuclear@8 523 {
nuclear@8 524 for(size_t i=0; i<stloc_cache.size(); i++) {
nuclear@8 525 setup_unistate(stloc_cache[i].sidx, this, stloc_cache[i].loc);
nuclear@8 526 }
nuclear@8 527 }
nuclear@8 528 */
nuclear@8 529
nuclear@8 530 // Static functions to use with ShaderSet
nuclear@8 531 Shader *Shader::create_shader()
nuclear@8 532 {
nuclear@8 533 return new Shader;
nuclear@8 534 }
nuclear@8 535
nuclear@8 536 bool Shader::load_shader(Shader *sdr, const char *fname)
nuclear@8 537 {
nuclear@8 538 std::string src = read_source(fname);
nuclear@8 539 if(src.empty()) {
nuclear@8 540 return false;
nuclear@8 541 }
nuclear@8 542
nuclear@8 543 sdr->src = src;
nuclear@8 544 return true;
nuclear@8 545 }
nuclear@8 546
nuclear@8 547 bool Shader::done_shader(Shader *sdr, unsigned int type)
nuclear@8 548 {
nuclear@8 549 return sdr->create(sdr->src.c_str(), type);
nuclear@8 550 }
nuclear@8 551
nuclear@8 552 /*
nuclear@8 553 static bool done_vertex_shader(Shader *sdr)
nuclear@8 554 {
nuclear@8 555 return Shader::done_shader(sdr, GL_VERTEX_SHADER);
nuclear@8 556 }
nuclear@8 557
nuclear@8 558 static bool done_pixel_shader(Shader *sdr)
nuclear@8 559 {
nuclear@8 560 return Shader::done_shader(sdr, GL_FRAGMENT_SHADER);
nuclear@8 561 }
nuclear@8 562
nuclear@8 563 #ifdef HAVE_GEOMETRY_SHADER
nuclear@8 564 static bool done_geom_shader(Shader *sdr)
nuclear@8 565 {
nuclear@8 566 return Shader::done_shader(sdr, GL_GEOMETRY_SHADER);
nuclear@8 567 }
nuclear@8 568 #endif
nuclear@8 569
nuclear@8 570 #ifdef HAVE_TESSELATION_SHADER
nuclear@8 571 static bool done_tc_shader(Shader *sdr)
nuclear@8 572 {
nuclear@8 573 return Shader::done_shader(sdr, GL_TESS_CONTROL_SHADER);
nuclear@8 574 }
nuclear@8 575
nuclear@8 576 static bool done_te_shader(Shader *sdr)
nuclear@8 577 {
nuclear@8 578 return Shader::done_shader(sdr, GL_TESS_EVALUATION_SHADER);
nuclear@8 579 }
nuclear@8 580 #endif
nuclear@8 581
nuclear@8 582 void Shader::destroy_shader(Shader *sdr)
nuclear@8 583 {
nuclear@8 584 delete sdr;
nuclear@8 585 }
nuclear@8 586
nuclear@8 587 // ---- ShaderSet ----
nuclear@8 588
nuclear@8 589 ShaderSet::ShaderSet(unsigned int type)
nuclear@8 590 : DataSet<Shader*>(Shader::create_shader, Shader::load_shader, 0, Shader::destroy_shader)
nuclear@8 591 {
nuclear@8 592 switch(type) {
nuclear@8 593 case GL_VERTEX_SHADER:
nuclear@8 594 done = done_vertex_shader;
nuclear@8 595 break;
nuclear@8 596
nuclear@8 597 case GL_FRAGMENT_SHADER:
nuclear@8 598 done = done_pixel_shader;
nuclear@8 599 break;
nuclear@8 600
nuclear@8 601 #ifdef HAVE_GEOMETRY_SHADER
nuclear@8 602 case GL_GEOMETRY_SHADER:
nuclear@8 603 done = done_geom_shader;
nuclear@8 604 break;
nuclear@8 605 #endif
nuclear@8 606
nuclear@8 607 #ifdef HAVE_TESSELATION_SHADER
nuclear@8 608 case GL_TESS_CONTROL_SHADER:
nuclear@8 609 done = done_tc_shader;
nuclear@8 610 break;
nuclear@8 611
nuclear@8 612 case GL_TESS_EVALUATION_SHADER:
nuclear@8 613 done = done_te_shader;
nuclear@8 614 break;
nuclear@8 615 #endif
nuclear@8 616
nuclear@8 617 default:
nuclear@8 618 fprintf(stderr, "ShaderSet constructed with invalid shader type!\n");
nuclear@8 619 }
nuclear@8 620 }
nuclear@8 621 */
nuclear@8 622
nuclear@8 623 static struct { const char *name; int loc; } attr_loc[] = {
nuclear@8 624 {"attr_vertex", MESH_ATTR_VERTEX},
nuclear@8 625 {"attr_normal", MESH_ATTR_NORMAL},
nuclear@8 626 {"attr_tangent", MESH_ATTR_TANGENT},
nuclear@8 627 {"attr_texcoord", MESH_ATTR_TEXCOORD},
nuclear@8 628 {"attr_color", MESH_ATTR_COLOR},
nuclear@8 629 {"attr_boneweights", MESH_ATTR_BONEWEIGHTS},
nuclear@8 630 {"attr_boneidx", MESH_ATTR_BONEIDX}
nuclear@8 631 };
nuclear@8 632
nuclear@8 633 static void bind_standard_attr(const ShaderProg *prog)
nuclear@8 634 {
nuclear@8 635 // we must link once to find out which are the active attributes
nuclear@8 636 glLinkProgram(prog->get_id());
nuclear@8 637
nuclear@8 638 int num_attr;
nuclear@8 639 glGetProgramiv(prog->get_id(), GL_ACTIVE_ATTRIBUTES, &num_attr);
nuclear@8 640
nuclear@8 641 char name[256];
nuclear@8 642 for(int i=0; i<num_attr; i++) {
nuclear@8 643 GLint sz;
nuclear@8 644 GLenum type;
nuclear@8 645 glGetActiveAttrib(prog->get_id(), i, sizeof name - 1, 0, &sz, &type, name);
nuclear@8 646
nuclear@8 647 for(int j=0; j<(int)(sizeof attr_loc / sizeof *attr_loc); j++) {
nuclear@8 648 if(strcmp(name, attr_loc[j].name) == 0) {
nuclear@8 649 prog->set_attrib_location(name, attr_loc[j].loc);
nuclear@8 650 }
nuclear@8 651 }
nuclear@8 652 }
nuclear@8 653 }
nuclear@8 654
nuclear@8 655
nuclear@8 656 /*
nuclear@8 657 static const char *strtype(unsigned int type)
nuclear@8 658 {
nuclear@8 659 switch(type) {
nuclear@8 660 case GL_VERTEX_SHADER:
nuclear@8 661 return "vertex";
nuclear@8 662 case GL_FRAGMENT_SHADER:
nuclear@8 663 return "fragment";
nuclear@8 664 #ifdef HAVE_GEOMETRY_SHADER
nuclear@8 665 case GL_GEOMETRY_SHADER:
nuclear@8 666 return "geometry";
nuclear@8 667 #endif
nuclear@8 668 #ifdef HAVE_TESSELATION_SHADER
nuclear@8 669 case GL_TESS_CONTROL_SHADER:
nuclear@8 670 return "tesselation control";
nuclear@8 671 case GL_TESS_EVALUATION_SHADER:
nuclear@8 672 return "tesselation evaluation";
nuclear@8 673 #endif
nuclear@8 674 default:
nuclear@8 675 break;
nuclear@8 676 }
nuclear@8 677 return "<unknown>";
nuclear@8 678 }
nuclear@8 679 */