3dphotoshoot

annotate src/shader.cc @ 20:c14613d27a3a

writing a C++ shader class for this
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 11 Jun 2015 02:53:43 +0300
parents
children 4ca4e3c5a754
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@20 10 SdrProg::SdrProg()
nuclear@20 11 {
nuclear@20 12 prog = 0;
nuclear@20 13 valid = false;
nuclear@20 14 }
nuclear@20 15
nuclear@20 16 SdrProg::~SdrProg()
nuclear@20 17 {
nuclear@20 18 destroy();
nuclear@20 19 }
nuclear@20 20
nuclear@20 21 void SdrProg::create()
nuclear@20 22 {
nuclear@20 23 destroy();
nuclear@20 24 prog = glCreateProgram();
nuclear@20 25 }
nuclear@20 26
nuclear@20 27 void SdrProg::destroy()
nuclear@20 28 {
nuclear@20 29 if(prog) {
nuclear@20 30 glDeleteProgram(prog);
nuclear@20 31 }
nuclear@20 32 valid = false;
nuclear@20 33
nuclear@20 34 for(size_t i=0; i<priv_sdr.size(); i++) {
nuclear@20 35 glDeleteShader(priv_sdr[i]);
nuclear@20 36 }
nuclear@20 37 priv_sdr.clear();
nuclear@20 38 }
nuclear@20 39
nuclear@20 40 bool SdrProg::attach_shader(unsigned int sdr)
nuclear@20 41 {
nuclear@20 42 assert(glGetError() == GL_NO_ERROR);
nuclear@20 43
nuclear@20 44 glAttachShader(prog, sdr);
nuclear@20 45 if(glGetError() != GL_NO_ERROR) {
nuclear@20 46 fprintf(stderr, "failed to attach shader %u to program %u\n", sdr, prog);
nuclear@20 47 return false;
nuclear@20 48 }
nuclear@20 49
nuclear@20 50 valid = false;
nuclear@20 51 return true;
nuclear@20 52 }
nuclear@20 53
nuclear@20 54 bool SdrProg::create(unsigned int vsdr, unsigned int psdr)
nuclear@20 55 {
nuclear@20 56 create();
nuclear@20 57
nuclear@20 58 if(!attach_shader(vsdr) || !attach_shader(psdr)) {
nuclear@20 59 return false;
nuclear@20 60 }
nuclear@20 61
nuclear@20 62 if(!link()) {
nuclear@20 63 return false;
nuclear@20 64 }
nuclear@20 65 return true;
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@20 94 unsigned int vs = load_vertex_shader(vfname);
nuclear@20 95 if(!vs) {
nuclear@20 96 return false;
nuclear@20 97 }
nuclear@20 98 sdrdb[vfname] = vs;
nuclear@20 99
nuclear@20 100 unsigned int ps = load_pixel_shader(pfname);
nuclear@20 101 if(!ps) {
nuclear@20 102 return false;
nuclear@20 103 }
nuclear@20 104 sdrdb[pfname] = ps;
nuclear@20 105
nuclear@20 106 printf("creating shader program (%s, %s)\n", vfname, pfname);
nuclear@20 107 if(!(prog = create_program_link(vs, ps, 0))) {
nuclear@20 108 return false;
nuclear@20 109 }
nuclear@20 110 valid = true;
nuclear@20 111 return true;
nuclear@20 112 }
nuclear@20 113
nuclear@20 114 bool SdrProg::link() const
nuclear@20 115 {
nuclear@20 116 return link_program(prog) != -1;
nuclear@20 117 }
nuclear@20 118
nuclear@20 119 int SdrProg::get_uniform(const char *name) const
nuclear@20 120 {
nuclear@20 121 if(!bind()) {
nuclear@20 122 return -1;
nuclear@20 123 }
nuclear@20 124 return glGetUniformLocation(prog, name);
nuclear@20 125 }
nuclear@20 126
nuclear@20 127 int SdrProg::get_attrib(const char *name) const
nuclear@20 128 {
nuclear@20 129 if(!bind()) {
nuclear@20 130 return -1;
nuclear@20 131 }
nuclear@20 132 return glGetAttribLocation(prog, name);
nuclear@20 133 }
nuclear@20 134
nuclear@20 135 bool SdrProg::bind_attrib(const char *name, int loc) const
nuclear@20 136 {
nuclear@20 137 if(!prog) {
nuclear@20 138 return false;
nuclear@20 139 }
nuclear@20 140
nuclear@20 141 assert(glGetError() == GL_NO_ERROR);
nuclear@20 142 glBindAttribLocation(prog, loc, name);
nuclear@20 143 if(glGetError() != GL_NO_ERROR) {
nuclear@20 144 fprintf(stderr, "failed to bind attribute %s of program %u to location %d\n",
nuclear@20 145 name, prog, loc);
nuclear@20 146 return false;
nuclear@20 147 }
nuclear@20 148 valid = false; /* must relink after the glBindAttribLocation call */
nuclear@20 149 return true;
nuclear@20 150 }
nuclear@20 151
nuclear@20 152 bool SdrProg::bind() const
nuclear@20 153 {
nuclear@20 154 if(!prog || (!valid && !link())) {
nuclear@20 155 return false;
nuclear@20 156 }
nuclear@20 157
nuclear@20 158 assert(glGetError() == GL_NO_ERROR);
nuclear@20 159 glUseProgram(prog);
nuclear@20 160 if(glGetError() != GL_NO_ERROR) {
nuclear@20 161 fprintf(stderr, "failed to bind program %d\n", prog);
nuclear@20 162 return false;
nuclear@20 163 }
nuclear@20 164 return true;
nuclear@20 165 }
nuclear@20 166
nuclear@20 167
nuclear@20 168 unsigned int get_shader(const char *name, unsigned int type)
nuclear@20 169 {
nuclear@20 170 std::map<std::string, unsigned int>::const_iterator it = sdrdb.find(name);
nuclear@20 171 if(it != sdrdb.end()) {
nuclear@20 172 return it->second;
nuclear@20 173 }
nuclear@20 174
nuclear@20 175 unsigned int sdr = load_shader(name, type);
nuclear@20 176 if(!sdr) {
nuclear@20 177 return 0;
nuclear@20 178 }
nuclear@20 179
nuclear@20 180 sdrdb[name] = sdr;
nuclear@20 181 return sdr;
nuclear@20 182 }