conworlds

annotate src/shader.cc @ 13:283cdfa7dda2

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