3dphotoshoot

annotate src/shader.cc @ 27:3d082c566b53

fixed all the bugs, pc version works
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 18 Jun 2015 04:32:25 +0300
parents 4ca4e3c5a754
children
rev   line source
nuclear@20 1 #include <assert.h>
nuclear@20 2 #include <string>
nuclear@20 3 #include <map>
nuclear@20 4 #include "shader.h"
nuclear@20 5 #include "sdr.h"
nuclear@20 6 #include "opengl.h"
nuclear@20 7
nuclear@20 8 std::map<std::string, unsigned int> sdrdb;
nuclear@20 9
nuclear@21 10 const SdrProg *SdrProg::active;
nuclear@21 11
nuclear@20 12 SdrProg::SdrProg()
nuclear@20 13 {
nuclear@20 14 prog = 0;
nuclear@20 15 valid = false;
nuclear@20 16 }
nuclear@20 17
nuclear@20 18 SdrProg::~SdrProg()
nuclear@20 19 {
nuclear@20 20 destroy();
nuclear@20 21 }
nuclear@20 22
nuclear@20 23 void SdrProg::create()
nuclear@20 24 {
nuclear@20 25 destroy();
nuclear@20 26 prog = glCreateProgram();
nuclear@20 27 }
nuclear@20 28
nuclear@20 29 void SdrProg::destroy()
nuclear@20 30 {
nuclear@20 31 if(prog) {
nuclear@20 32 glDeleteProgram(prog);
nuclear@20 33 }
nuclear@20 34 valid = false;
nuclear@20 35
nuclear@20 36 for(size_t i=0; i<priv_sdr.size(); i++) {
nuclear@20 37 glDeleteShader(priv_sdr[i]);
nuclear@20 38 }
nuclear@20 39 priv_sdr.clear();
nuclear@20 40 }
nuclear@20 41
nuclear@20 42 bool SdrProg::attach_shader(unsigned int sdr)
nuclear@20 43 {
nuclear@20 44 assert(glGetError() == GL_NO_ERROR);
nuclear@20 45
nuclear@20 46 glAttachShader(prog, sdr);
nuclear@20 47 if(glGetError() != GL_NO_ERROR) {
nuclear@20 48 fprintf(stderr, "failed to attach shader %u to program %u\n", sdr, prog);
nuclear@20 49 return false;
nuclear@20 50 }
nuclear@20 51
nuclear@20 52 valid = false;
nuclear@20 53 return true;
nuclear@20 54 }
nuclear@20 55
nuclear@20 56 bool SdrProg::create(unsigned int vsdr, unsigned int psdr)
nuclear@20 57 {
nuclear@20 58 create();
nuclear@20 59
nuclear@20 60 if(!attach_shader(vsdr) || !attach_shader(psdr)) {
nuclear@20 61 return false;
nuclear@20 62 }
nuclear@20 63
nuclear@21 64 bind_default_attribs();
nuclear@21 65 return link();
nuclear@20 66 }
nuclear@20 67
nuclear@20 68 bool SdrProg::create(const char *vsrc, const char *psrc)
nuclear@20 69 {
nuclear@20 70 unsigned int vs = create_shader(vsrc, GL_VERTEX_SHADER);
nuclear@20 71 if(!vs) {
nuclear@20 72 return false;
nuclear@20 73 }
nuclear@20 74
nuclear@20 75 unsigned int ps = create_shader(psrc, GL_FRAGMENT_SHADER);
nuclear@20 76 if(!ps) {
nuclear@20 77 glDeleteShader(vs);
nuclear@20 78 return false;
nuclear@20 79 }
nuclear@20 80
nuclear@20 81 if(!create(vs, ps)) {
nuclear@20 82 glDeleteShader(vs);
nuclear@20 83 glDeleteShader(ps);
nuclear@20 84 return false;
nuclear@20 85 }
nuclear@20 86
nuclear@20 87 priv_sdr.push_back(vs);
nuclear@20 88 priv_sdr.push_back(ps);
nuclear@20 89 return true;
nuclear@20 90 }
nuclear@20 91
nuclear@20 92 bool SdrProg::load(const char *vfname, const char *pfname)
nuclear@20 93 {
nuclear@21 94 unsigned int vs = get_shader(vfname, GL_VERTEX_SHADER);
nuclear@20 95 if(!vs) {
nuclear@20 96 return false;
nuclear@20 97 }
nuclear@20 98
nuclear@21 99 unsigned int ps = get_shader(pfname, GL_FRAGMENT_SHADER);
nuclear@20 100 if(!ps) {
nuclear@20 101 return false;
nuclear@20 102 }
nuclear@20 103
nuclear@20 104 printf("creating shader program (%s, %s)\n", vfname, pfname);
nuclear@20 105 if(!(prog = create_program_link(vs, ps, 0))) {
nuclear@20 106 return false;
nuclear@20 107 }
nuclear@21 108
nuclear@21 109 bind_default_attribs();
nuclear@21 110 return link();
nuclear@20 111 }
nuclear@20 112
nuclear@20 113 bool SdrProg::link() const
nuclear@20 114 {
nuclear@21 115 if(link_program(prog) == -1) {
nuclear@21 116 return false;
nuclear@21 117 }
nuclear@21 118 valid = true;
nuclear@21 119 return true;
nuclear@20 120 }
nuclear@20 121
nuclear@20 122 int SdrProg::get_uniform(const char *name) const
nuclear@20 123 {
nuclear@20 124 if(!bind()) {
nuclear@20 125 return -1;
nuclear@20 126 }
nuclear@20 127 return glGetUniformLocation(prog, name);
nuclear@20 128 }
nuclear@20 129
nuclear@20 130 int SdrProg::get_attrib(const char *name) const
nuclear@20 131 {
nuclear@20 132 if(!bind()) {
nuclear@20 133 return -1;
nuclear@20 134 }
nuclear@20 135 return glGetAttribLocation(prog, name);
nuclear@20 136 }
nuclear@20 137
nuclear@20 138 bool SdrProg::bind_attrib(const char *name, int loc) const
nuclear@20 139 {
nuclear@20 140 if(!prog) {
nuclear@20 141 return false;
nuclear@20 142 }
nuclear@20 143
nuclear@20 144 assert(glGetError() == GL_NO_ERROR);
nuclear@20 145 glBindAttribLocation(prog, loc, name);
nuclear@20 146 if(glGetError() != GL_NO_ERROR) {
nuclear@20 147 fprintf(stderr, "failed to bind attribute %s of program %u to location %d\n",
nuclear@20 148 name, prog, loc);
nuclear@20 149 return false;
nuclear@20 150 }
nuclear@20 151 valid = false; /* must relink after the glBindAttribLocation call */
nuclear@20 152 return true;
nuclear@20 153 }
nuclear@20 154
nuclear@21 155 void SdrProg::bind_default_attribs() const
nuclear@21 156 {
nuclear@21 157 // XXX must be in sync with SdrDefaultAttrib enums in shader.h
nuclear@21 158 static const char *def_names[] = {
nuclear@21 159 "attr_vertex",
nuclear@21 160 "attr_normal",
nuclear@21 161 "attr_texcoord",
nuclear@21 162 "attr_color",
nuclear@21 163 "attr_tangent",
nuclear@21 164 0
nuclear@21 165 };
nuclear@21 166
nuclear@21 167 for(int i=0; def_names[i]; i++) {
nuclear@21 168 bind_attrib(def_names[i], i);
nuclear@21 169 }
nuclear@21 170 }
nuclear@21 171
nuclear@21 172
nuclear@20 173 bool SdrProg::bind() const
nuclear@20 174 {
nuclear@20 175 if(!prog || (!valid && !link())) {
nuclear@20 176 return false;
nuclear@20 177 }
nuclear@20 178
nuclear@20 179 assert(glGetError() == GL_NO_ERROR);
nuclear@20 180 glUseProgram(prog);
nuclear@20 181 if(glGetError() != GL_NO_ERROR) {
nuclear@20 182 fprintf(stderr, "failed to bind program %d\n", prog);
nuclear@20 183 return false;
nuclear@20 184 }
nuclear@21 185
nuclear@21 186 active = this;
nuclear@20 187 return true;
nuclear@20 188 }
nuclear@20 189
nuclear@22 190 void SdrProg::set_uniform(const char *name, int count, const int *val) const
nuclear@22 191 {
nuclear@22 192 if(!bind()) return;
nuclear@22 193
nuclear@22 194 int loc = glGetUniformLocation(prog, name);
nuclear@22 195 if(loc == -1) return;
nuclear@22 196
nuclear@22 197 switch(count) {
nuclear@22 198 case 1:
nuclear@22 199 glUniform1iv(loc, 1, val);
nuclear@22 200 break;
nuclear@22 201 case 2:
nuclear@22 202 glUniform2iv(loc, 1, val);
nuclear@22 203 break;
nuclear@22 204 case 3:
nuclear@22 205 glUniform3iv(loc, 1, val);
nuclear@22 206 case 4:
nuclear@22 207 glUniform4iv(loc, 1, val);
nuclear@22 208 default:
nuclear@22 209 break;
nuclear@22 210 }
nuclear@22 211 }
nuclear@22 212
nuclear@22 213 void SdrProg::set_uniform(const char *name, int count, const float *val) const
nuclear@22 214 {
nuclear@22 215 if(!bind()) return;
nuclear@22 216
nuclear@22 217 int loc = glGetUniformLocation(prog, name);
nuclear@22 218 if(loc == -1) return;
nuclear@22 219
nuclear@22 220 switch(count) {
nuclear@22 221 case 1:
nuclear@22 222 glUniform1fv(loc, 1, val);
nuclear@22 223 break;
nuclear@22 224 case 2:
nuclear@22 225 glUniform2fv(loc, 1, val);
nuclear@22 226 break;
nuclear@22 227 case 3:
nuclear@22 228 glUniform3fv(loc, 1, val);
nuclear@22 229 case 4:
nuclear@22 230 glUniform4fv(loc, 1, val);
nuclear@22 231 default:
nuclear@22 232 break;
nuclear@22 233 }
nuclear@22 234 }
nuclear@22 235
nuclear@22 236 void SdrProg::set_uniform(const char *name, const Vector4 &v) const
nuclear@22 237 {
nuclear@22 238 set_uniform(name, 4, &v.x);
nuclear@22 239 }
nuclear@22 240
nuclear@22 241
nuclear@22 242 void SdrProg::set_uniform1i(const char *name, int x) const
nuclear@22 243 {
nuclear@22 244 set_uniform(name, 1, &x);
nuclear@22 245 }
nuclear@22 246
nuclear@22 247 void SdrProg::set_uniform2i(const char *name, int x, int y) const
nuclear@22 248 {
nuclear@22 249 int v[] = {x, y};
nuclear@22 250 set_uniform(name, 2, v);
nuclear@22 251 }
nuclear@22 252
nuclear@22 253 void SdrProg::set_uniform3i(const char *name, int x, int y, int z) const
nuclear@22 254 {
nuclear@22 255 int v[] = {x, y, z};
nuclear@22 256 set_uniform(name, 3, v);
nuclear@22 257 }
nuclear@22 258
nuclear@22 259 void SdrProg::set_uniform4i(const char *name, int x, int y, int z, int w) const
nuclear@22 260 {
nuclear@22 261 int v[] = {x, y, z, w};
nuclear@22 262 set_uniform(name, 4, v);
nuclear@22 263 }
nuclear@22 264
nuclear@22 265 void SdrProg::set_uniform1f(const char *name, float x) const
nuclear@22 266 {
nuclear@22 267 set_uniform(name, 1, &x);
nuclear@22 268 }
nuclear@22 269
nuclear@22 270 void SdrProg::set_uniform2f(const char *name, float x, float y) const
nuclear@22 271 {
nuclear@22 272 float v[] = {x, y};
nuclear@22 273 set_uniform(name, 2, v);
nuclear@22 274 }
nuclear@22 275
nuclear@22 276 void SdrProg::set_uniform3f(const char *name, float x, float y, float z) const
nuclear@22 277 {
nuclear@22 278 float v[] = {x, y, z};
nuclear@22 279 set_uniform(name, 3, v);
nuclear@22 280 }
nuclear@22 281
nuclear@22 282 void SdrProg::set_uniform4f(const char *name, float x, float y, float z, float w) const
nuclear@22 283 {
nuclear@22 284 float v[] = {x, y, z, w};
nuclear@22 285 set_uniform(name, 4, v);
nuclear@22 286 }
nuclear@22 287
nuclear@22 288 void SdrProg::set_uniform_matrix(const char *name, const float *m) const
nuclear@22 289 {
nuclear@22 290 if(!bind()) return;
nuclear@22 291
nuclear@22 292 int loc = glGetUniformLocation(prog, name);
nuclear@22 293 if(loc == -1) return;
nuclear@22 294
nuclear@22 295 glUniformMatrix4fv(loc, 1, 0, m);
nuclear@22 296 }
nuclear@22 297
nuclear@22 298 void SdrProg::set_uniform_matrix(const char *name, const Matrix4x4 &m) const
nuclear@22 299 {
nuclear@22 300 Matrix4x4 tmp = m.transposed();
nuclear@22 301 set_uniform_matrix(name, tmp[0]);
nuclear@22 302 }
nuclear@22 303
nuclear@22 304
nuclear@22 305
nuclear@20 306 unsigned int get_shader(const char *name, unsigned int type)
nuclear@20 307 {
nuclear@20 308 std::map<std::string, unsigned int>::const_iterator it = sdrdb.find(name);
nuclear@20 309 if(it != sdrdb.end()) {
nuclear@20 310 return it->second;
nuclear@20 311 }
nuclear@20 312
nuclear@20 313 unsigned int sdr = load_shader(name, type);
nuclear@20 314 if(!sdr) {
nuclear@20 315 return 0;
nuclear@20 316 }
nuclear@20 317
nuclear@20 318 sdrdb[name] = sdr;
nuclear@20 319 return sdr;
nuclear@20 320 }
nuclear@21 321
nuclear@21 322 SdrProg *get_sdrprog(const char *vfile, const char *pfile)
nuclear@21 323 {
nuclear@21 324 SdrProg *sp = new SdrProg;
nuclear@21 325 if(!sp->load(vfile, pfile)) {
nuclear@21 326 delete sp;
nuclear@21 327 return 0;
nuclear@21 328 }
nuclear@21 329 return sp;
nuclear@21 330 }