3dphotoshoot

annotate src/shader.cc @ 21:4ca4e3c5a754

port to C++ completed, shader programs now use the SdrProg class
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 11 Jun 2015 04:56:33 +0300
parents c14613d27a3a
children d7fe157c402d
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@20 190 unsigned int get_shader(const char *name, unsigned int type)
nuclear@20 191 {
nuclear@20 192 std::map<std::string, unsigned int>::const_iterator it = sdrdb.find(name);
nuclear@20 193 if(it != sdrdb.end()) {
nuclear@20 194 return it->second;
nuclear@20 195 }
nuclear@20 196
nuclear@20 197 unsigned int sdr = load_shader(name, type);
nuclear@20 198 if(!sdr) {
nuclear@20 199 return 0;
nuclear@20 200 }
nuclear@20 201
nuclear@20 202 sdrdb[name] = sdr;
nuclear@20 203 return sdr;
nuclear@20 204 }
nuclear@21 205
nuclear@21 206 SdrProg *get_sdrprog(const char *vfile, const char *pfile)
nuclear@21 207 {
nuclear@21 208 SdrProg *sp = new SdrProg;
nuclear@21 209 if(!sp->load(vfile, pfile)) {
nuclear@21 210 delete sp;
nuclear@21 211 return 0;
nuclear@21 212 }
nuclear@21 213 return sp;
nuclear@21 214 }