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