3dphotoshoot
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/shader.cc Thu Jun 11 02:53:43 2015 +0300 1.3 @@ -0,0 +1,182 @@ 1.4 +#include <assert.h> 1.5 +#include <string> 1.6 +#include <map> 1.7 +#include "shader.h" 1.8 +#include "sdr.h" 1.9 +#include "opengl.h" 1.10 + 1.11 +std::map<std::string, unsigned int> sdrdb; 1.12 + 1.13 +SdrProg::SdrProg() 1.14 +{ 1.15 + prog = 0; 1.16 + valid = false; 1.17 +} 1.18 + 1.19 +SdrProg::~SdrProg() 1.20 +{ 1.21 + destroy(); 1.22 +} 1.23 + 1.24 +void SdrProg::create() 1.25 +{ 1.26 + destroy(); 1.27 + prog = glCreateProgram(); 1.28 +} 1.29 + 1.30 +void SdrProg::destroy() 1.31 +{ 1.32 + if(prog) { 1.33 + glDeleteProgram(prog); 1.34 + } 1.35 + valid = false; 1.36 + 1.37 + for(size_t i=0; i<priv_sdr.size(); i++) { 1.38 + glDeleteShader(priv_sdr[i]); 1.39 + } 1.40 + priv_sdr.clear(); 1.41 +} 1.42 + 1.43 +bool SdrProg::attach_shader(unsigned int sdr) 1.44 +{ 1.45 + assert(glGetError() == GL_NO_ERROR); 1.46 + 1.47 + glAttachShader(prog, sdr); 1.48 + if(glGetError() != GL_NO_ERROR) { 1.49 + fprintf(stderr, "failed to attach shader %u to program %u\n", sdr, prog); 1.50 + return false; 1.51 + } 1.52 + 1.53 + valid = false; 1.54 + return true; 1.55 +} 1.56 + 1.57 +bool SdrProg::create(unsigned int vsdr, unsigned int psdr) 1.58 +{ 1.59 + create(); 1.60 + 1.61 + if(!attach_shader(vsdr) || !attach_shader(psdr)) { 1.62 + return false; 1.63 + } 1.64 + 1.65 + if(!link()) { 1.66 + return false; 1.67 + } 1.68 + return true; 1.69 +} 1.70 + 1.71 +bool SdrProg::create(const char *vsrc, const char *psrc) 1.72 +{ 1.73 + unsigned int vs = create_shader(vsrc, GL_VERTEX_SHADER); 1.74 + if(!vs) { 1.75 + return false; 1.76 + } 1.77 + 1.78 + unsigned int ps = create_shader(psrc, GL_FRAGMENT_SHADER); 1.79 + if(!ps) { 1.80 + glDeleteShader(vs); 1.81 + return false; 1.82 + } 1.83 + 1.84 + if(!create(vs, ps)) { 1.85 + glDeleteShader(vs); 1.86 + glDeleteShader(ps); 1.87 + return false; 1.88 + } 1.89 + 1.90 + priv_sdr.push_back(vs); 1.91 + priv_sdr.push_back(ps); 1.92 + return true; 1.93 +} 1.94 + 1.95 +bool SdrProg::load(const char *vfname, const char *pfname) 1.96 +{ 1.97 + unsigned int vs = load_vertex_shader(vfname); 1.98 + if(!vs) { 1.99 + return false; 1.100 + } 1.101 + sdrdb[vfname] = vs; 1.102 + 1.103 + unsigned int ps = load_pixel_shader(pfname); 1.104 + if(!ps) { 1.105 + return false; 1.106 + } 1.107 + sdrdb[pfname] = ps; 1.108 + 1.109 + printf("creating shader program (%s, %s)\n", vfname, pfname); 1.110 + if(!(prog = create_program_link(vs, ps, 0))) { 1.111 + return false; 1.112 + } 1.113 + valid = true; 1.114 + return true; 1.115 +} 1.116 + 1.117 +bool SdrProg::link() const 1.118 +{ 1.119 + return link_program(prog) != -1; 1.120 +} 1.121 + 1.122 +int SdrProg::get_uniform(const char *name) const 1.123 +{ 1.124 + if(!bind()) { 1.125 + return -1; 1.126 + } 1.127 + return glGetUniformLocation(prog, name); 1.128 +} 1.129 + 1.130 +int SdrProg::get_attrib(const char *name) const 1.131 +{ 1.132 + if(!bind()) { 1.133 + return -1; 1.134 + } 1.135 + return glGetAttribLocation(prog, name); 1.136 +} 1.137 + 1.138 +bool SdrProg::bind_attrib(const char *name, int loc) const 1.139 +{ 1.140 + if(!prog) { 1.141 + return false; 1.142 + } 1.143 + 1.144 + assert(glGetError() == GL_NO_ERROR); 1.145 + glBindAttribLocation(prog, loc, name); 1.146 + if(glGetError() != GL_NO_ERROR) { 1.147 + fprintf(stderr, "failed to bind attribute %s of program %u to location %d\n", 1.148 + name, prog, loc); 1.149 + return false; 1.150 + } 1.151 + valid = false; /* must relink after the glBindAttribLocation call */ 1.152 + return true; 1.153 +} 1.154 + 1.155 +bool SdrProg::bind() const 1.156 +{ 1.157 + if(!prog || (!valid && !link())) { 1.158 + return false; 1.159 + } 1.160 + 1.161 + assert(glGetError() == GL_NO_ERROR); 1.162 + glUseProgram(prog); 1.163 + if(glGetError() != GL_NO_ERROR) { 1.164 + fprintf(stderr, "failed to bind program %d\n", prog); 1.165 + return false; 1.166 + } 1.167 + return true; 1.168 +} 1.169 + 1.170 + 1.171 +unsigned int get_shader(const char *name, unsigned int type) 1.172 +{ 1.173 + std::map<std::string, unsigned int>::const_iterator it = sdrdb.find(name); 1.174 + if(it != sdrdb.end()) { 1.175 + return it->second; 1.176 + } 1.177 + 1.178 + unsigned int sdr = load_shader(name, type); 1.179 + if(!sdr) { 1.180 + return 0; 1.181 + } 1.182 + 1.183 + sdrdb[name] = sdr; 1.184 + return sdr; 1.185 +}