rev |
line source |
nuclear@8
|
1 #include <stdio.h>
|
nuclear@8
|
2 #include <string.h>
|
nuclear@8
|
3 #include <stdarg.h>
|
nuclear@8
|
4 #include <errno.h>
|
nuclear@8
|
5 #include "opengl.h"
|
nuclear@8
|
6 #include "shader.h"
|
nuclear@8
|
7 #include "mesh.h"
|
nuclear@8
|
8
|
nuclear@8
|
9 #ifdef _MSC_VER
|
nuclear@8
|
10 #include <malloc.h>
|
nuclear@8
|
11 #else
|
nuclear@8
|
12 #include <alloca.h>
|
nuclear@8
|
13 #endif
|
nuclear@8
|
14
|
nuclear@8
|
15 #ifdef __GLEW_H__
|
nuclear@8
|
16 #define HAVE_GEOMETRY_SHADER
|
nuclear@8
|
17 #define HAVE_TESSELATION_SHADER
|
nuclear@8
|
18 #endif
|
nuclear@8
|
19
|
nuclear@8
|
20 static std::string read_source(const char *fname);
|
nuclear@8
|
21 static void bind_standard_attr(const ShaderProg *prog);
|
nuclear@8
|
22
|
nuclear@8
|
23 ShaderProg *ShaderProg::current;
|
nuclear@8
|
24
|
nuclear@8
|
25 void bind_shader(const ShaderProg *sdr)
|
nuclear@8
|
26 {
|
nuclear@8
|
27 if(sdr) {
|
nuclear@8
|
28 sdr->bind();
|
nuclear@8
|
29 } else {
|
nuclear@8
|
30 #ifndef GL_ES_VERSION_2_0
|
nuclear@8
|
31 glUseProgram(0);
|
nuclear@8
|
32 ShaderProg::current = 0;
|
nuclear@8
|
33 #endif
|
nuclear@8
|
34 }
|
nuclear@8
|
35 }
|
nuclear@8
|
36
|
nuclear@8
|
37 const ShaderProg *get_current_shader()
|
nuclear@8
|
38 {
|
nuclear@8
|
39 return ShaderProg::current;
|
nuclear@8
|
40 }
|
nuclear@8
|
41
|
nuclear@8
|
42 Shader::Shader()
|
nuclear@8
|
43 {
|
nuclear@8
|
44 sdr = type = 0;
|
nuclear@8
|
45 }
|
nuclear@8
|
46
|
nuclear@8
|
47 Shader::~Shader()
|
nuclear@8
|
48 {
|
nuclear@8
|
49 destroy();
|
nuclear@8
|
50 }
|
nuclear@8
|
51
|
nuclear@8
|
52 unsigned int Shader::get_id() const
|
nuclear@8
|
53 {
|
nuclear@8
|
54 return sdr;
|
nuclear@8
|
55 }
|
nuclear@8
|
56
|
nuclear@8
|
57 void Shader::set_name(const char *name)
|
nuclear@8
|
58 {
|
nuclear@8
|
59 this->name = std::string(name);
|
nuclear@8
|
60 }
|
nuclear@8
|
61
|
nuclear@8
|
62 const char *Shader::get_name() const
|
nuclear@8
|
63 {
|
nuclear@8
|
64 return name.c_str();
|
nuclear@8
|
65 }
|
nuclear@8
|
66
|
nuclear@8
|
67 bool Shader::create(const char *src, unsigned int type)
|
nuclear@8
|
68 {
|
nuclear@8
|
69 #if !GL_ES_VERSION_2_0
|
nuclear@8
|
70 const char *src_arr[] = {src};
|
nuclear@8
|
71 #else
|
nuclear@8
|
72 const char *src_arr[] = { "precision mediump float; ", src };
|
nuclear@8
|
73 #endif
|
nuclear@8
|
74
|
nuclear@8
|
75 // keep a copy of the source code
|
nuclear@8
|
76 this->src = std::string(src);
|
nuclear@8
|
77
|
nuclear@8
|
78 if(!sdr) {
|
nuclear@8
|
79 sdr = glCreateShader(type);
|
nuclear@8
|
80 }
|
nuclear@8
|
81
|
nuclear@8
|
82 printf("compiling shader: %s... ", name.c_str());
|
nuclear@8
|
83
|
nuclear@8
|
84 glShaderSource(sdr, sizeof src_arr / sizeof *src_arr, src_arr, 0);
|
nuclear@8
|
85 glCompileShader(sdr);
|
nuclear@8
|
86
|
nuclear@8
|
87 int status;
|
nuclear@8
|
88 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
|
nuclear@8
|
89
|
nuclear@8
|
90 printf(status ? "success\n" : "failed\n");
|
nuclear@8
|
91
|
nuclear@8
|
92 int info_len;
|
nuclear@8
|
93 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len);
|
nuclear@8
|
94 if(info_len > 1) {
|
nuclear@8
|
95 char *buf = (char*)alloca(info_len);
|
nuclear@8
|
96 glGetShaderInfoLog(sdr, info_len, 0, buf);
|
nuclear@8
|
97 buf[info_len - 1] = 0;
|
nuclear@8
|
98
|
nuclear@8
|
99 if(status) {
|
nuclear@8
|
100 printf("%s\n", buf);
|
nuclear@8
|
101 } else {
|
nuclear@8
|
102 fprintf(stderr, "%s\n", buf);
|
nuclear@8
|
103 }
|
nuclear@8
|
104 }
|
nuclear@8
|
105
|
nuclear@8
|
106 return status == GL_TRUE;
|
nuclear@8
|
107 }
|
nuclear@8
|
108
|
nuclear@8
|
109 void Shader::destroy()
|
nuclear@8
|
110 {
|
nuclear@8
|
111 if(sdr) {
|
nuclear@8
|
112 glDeleteShader(sdr);
|
nuclear@8
|
113 }
|
nuclear@8
|
114 sdr = type = 0;
|
nuclear@8
|
115
|
nuclear@8
|
116 src.clear();
|
nuclear@8
|
117 name.clear();
|
nuclear@8
|
118 }
|
nuclear@8
|
119
|
nuclear@8
|
120 static std::string read_source(const char *fname)
|
nuclear@8
|
121 {
|
nuclear@8
|
122 FILE *fp;
|
nuclear@8
|
123
|
nuclear@8
|
124 if(!(fp = fopen(fname, "rb"))) {
|
nuclear@8
|
125 fprintf(stderr, "failed to load shader: %s: %s\n", fname, strerror(errno));
|
nuclear@8
|
126 return std::string();
|
nuclear@8
|
127 }
|
nuclear@8
|
128
|
nuclear@8
|
129 fseek(fp, 0, SEEK_END);
|
nuclear@8
|
130 long sz = ftell(fp);
|
nuclear@8
|
131 rewind(fp);
|
nuclear@8
|
132
|
nuclear@8
|
133 char *src = (char*)alloca(sz + 1);
|
nuclear@8
|
134 if(fread(src, 1, sz, fp) < (size_t)sz) {
|
nuclear@8
|
135 fprintf(stderr, "failed to load shader: %s: %s\n", fname, strerror(errno));
|
nuclear@8
|
136 fclose(fp);
|
nuclear@8
|
137 delete [] src;
|
nuclear@8
|
138 return std::string();
|
nuclear@8
|
139 }
|
nuclear@8
|
140 src[sz] = 0;
|
nuclear@8
|
141 fclose(fp);
|
nuclear@8
|
142
|
nuclear@8
|
143 return std::string(src);
|
nuclear@8
|
144 }
|
nuclear@8
|
145
|
nuclear@8
|
146 bool Shader::load(const char *fname, unsigned int type)
|
nuclear@8
|
147 {
|
nuclear@8
|
148 std::string src = read_source(fname);
|
nuclear@8
|
149 if(src.empty()) {
|
nuclear@8
|
150 return false;
|
nuclear@8
|
151 }
|
nuclear@8
|
152 set_name(fname);
|
nuclear@8
|
153 return create(src.c_str(), type);
|
nuclear@8
|
154 }
|
nuclear@8
|
155
|
nuclear@8
|
156 // ---- shader program ----
|
nuclear@8
|
157 ShaderProg::ShaderProg()
|
nuclear@8
|
158 {
|
nuclear@8
|
159 prog = 0;
|
nuclear@8
|
160 must_link = true;
|
nuclear@8
|
161 }
|
nuclear@8
|
162
|
nuclear@8
|
163 ShaderProg::~ShaderProg()
|
nuclear@8
|
164 {
|
nuclear@8
|
165 destroy();
|
nuclear@8
|
166 }
|
nuclear@8
|
167
|
nuclear@8
|
168 unsigned int ShaderProg::get_id() const
|
nuclear@8
|
169 {
|
nuclear@8
|
170 return prog;
|
nuclear@8
|
171 }
|
nuclear@8
|
172
|
nuclear@8
|
173 bool ShaderProg::create(const char *src, unsigned int type, ...)
|
nuclear@8
|
174 {
|
nuclear@8
|
175 va_list ap;
|
nuclear@8
|
176
|
nuclear@8
|
177 va_start(ap, type);
|
nuclear@8
|
178 bool res = create(src, type, ap);
|
nuclear@8
|
179 va_end(ap);
|
nuclear@8
|
180
|
nuclear@8
|
181 return res;
|
nuclear@8
|
182 }
|
nuclear@8
|
183
|
nuclear@8
|
184 bool ShaderProg::create(const char *src, unsigned int type, va_list ap)
|
nuclear@8
|
185 {
|
nuclear@8
|
186 destroy();
|
nuclear@8
|
187 prog = glCreateProgram();
|
nuclear@8
|
188
|
nuclear@8
|
189 while(src) {
|
nuclear@8
|
190 Shader *sdr = new Shader;
|
nuclear@8
|
191 if(!sdr->create(src, type)) {
|
nuclear@8
|
192 va_end(ap);
|
nuclear@8
|
193 return false;
|
nuclear@8
|
194 }
|
nuclear@8
|
195 add_shader(sdr);
|
nuclear@8
|
196 src = va_arg(ap, const char*);
|
nuclear@8
|
197 type = va_arg(ap, unsigned int);
|
nuclear@8
|
198 }
|
nuclear@8
|
199
|
nuclear@8
|
200 return link();
|
nuclear@8
|
201 }
|
nuclear@8
|
202
|
nuclear@8
|
203 bool ShaderProg::create(const char *vsrc, const char *psrc)
|
nuclear@8
|
204 {
|
nuclear@8
|
205 return create(VSDR(vsrc), PSDR(psrc), 0);
|
nuclear@8
|
206 }
|
nuclear@8
|
207
|
nuclear@8
|
208 bool ShaderProg::create(Shader *sdr, ...)
|
nuclear@8
|
209 {
|
nuclear@8
|
210 va_list ap;
|
nuclear@8
|
211
|
nuclear@8
|
212 va_start(ap, sdr);
|
nuclear@8
|
213 bool res = create(sdr, ap);
|
nuclear@8
|
214 va_end(ap);
|
nuclear@8
|
215
|
nuclear@8
|
216 return res;
|
nuclear@8
|
217 }
|
nuclear@8
|
218
|
nuclear@8
|
219 bool ShaderProg::create(Shader *sdr, va_list ap)
|
nuclear@8
|
220 {
|
nuclear@8
|
221 destroy();
|
nuclear@8
|
222 prog = glCreateProgram();
|
nuclear@8
|
223
|
nuclear@8
|
224 while(sdr) {
|
nuclear@8
|
225 add_shader(sdr);
|
nuclear@8
|
226 sdr = va_arg(ap, Shader*);
|
nuclear@8
|
227 }
|
nuclear@8
|
228 return link();
|
nuclear@8
|
229 }
|
nuclear@8
|
230
|
nuclear@8
|
231 bool ShaderProg::create(Shader *vsdr, Shader *psdr)
|
nuclear@8
|
232 {
|
nuclear@8
|
233 return create(vsdr, psdr, 0);
|
nuclear@8
|
234 }
|
nuclear@8
|
235
|
nuclear@8
|
236 void ShaderProg::destroy()
|
nuclear@8
|
237 {
|
nuclear@8
|
238 if(prog) {
|
nuclear@8
|
239 glDeleteProgram(prog);
|
nuclear@8
|
240 }
|
nuclear@8
|
241 prog = 0;
|
nuclear@8
|
242
|
nuclear@8
|
243 shaders.clear();
|
nuclear@8
|
244 // don't actually destroy the shaders, let the ShaderSet own them
|
nuclear@8
|
245 }
|
nuclear@8
|
246
|
nuclear@8
|
247 bool ShaderProg::load(const char *fname, unsigned int type, ...)
|
nuclear@8
|
248 {
|
nuclear@8
|
249 va_list ap;
|
nuclear@8
|
250 va_start(ap, type);
|
nuclear@8
|
251 bool res = load(fname, type, ap);
|
nuclear@8
|
252 va_end(ap);
|
nuclear@8
|
253
|
nuclear@8
|
254 return res;
|
nuclear@8
|
255 }
|
nuclear@8
|
256
|
nuclear@8
|
257 bool ShaderProg::load(const char *fname, unsigned int type, va_list ap)
|
nuclear@8
|
258 {
|
nuclear@8
|
259 destroy();
|
nuclear@8
|
260 prog = glCreateProgram();
|
nuclear@8
|
261
|
nuclear@8
|
262 while(fname) {
|
nuclear@8
|
263 Shader *sdr = new Shader;
|
nuclear@8
|
264 if(!sdr->load(fname, type)) {
|
nuclear@8
|
265 delete sdr;
|
nuclear@8
|
266 return false;
|
nuclear@8
|
267 }
|
nuclear@8
|
268 add_shader(sdr);
|
nuclear@8
|
269
|
nuclear@8
|
270 if((fname = va_arg(ap, const char*))) {
|
nuclear@8
|
271 type = va_arg(ap, unsigned int);
|
nuclear@8
|
272 }
|
nuclear@8
|
273 }
|
nuclear@8
|
274
|
nuclear@8
|
275 return link();
|
nuclear@8
|
276 }
|
nuclear@8
|
277
|
nuclear@8
|
278 bool ShaderProg::load(const char *vfname, const char *pfname)
|
nuclear@8
|
279 {
|
nuclear@8
|
280 return load(VSDR(vfname), PSDR(pfname), 0);
|
nuclear@8
|
281 }
|
nuclear@8
|
282
|
nuclear@8
|
283 void ShaderProg::add_shader(Shader *sdr)
|
nuclear@8
|
284 {
|
nuclear@8
|
285 glAttachShader(prog, sdr->get_id());
|
nuclear@8
|
286 }
|
nuclear@8
|
287
|
nuclear@8
|
288 bool ShaderProg::link() const
|
nuclear@8
|
289 {
|
nuclear@8
|
290 bind_standard_attr(this);
|
nuclear@8
|
291
|
nuclear@8
|
292 printf("linking program ... ");
|
nuclear@8
|
293 glLinkProgram(prog);
|
nuclear@8
|
294
|
nuclear@8
|
295 int status;
|
nuclear@8
|
296 glGetProgramiv(prog, GL_LINK_STATUS, &status);
|
nuclear@8
|
297
|
nuclear@8
|
298 printf(status ? "success\n" : "failed\n");
|
nuclear@8
|
299
|
nuclear@8
|
300 int info_len;
|
nuclear@8
|
301 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len);
|
nuclear@8
|
302 if(info_len > 1) {
|
nuclear@8
|
303 char *buf = (char*)alloca(info_len);
|
nuclear@8
|
304 glGetProgramInfoLog(prog, info_len, 0, buf);
|
nuclear@8
|
305 buf[info_len - 1] = 0;
|
nuclear@8
|
306
|
nuclear@8
|
307 if(status) {
|
nuclear@8
|
308 printf("%s\n", buf);
|
nuclear@8
|
309 } else {
|
nuclear@8
|
310 fprintf(stderr, "%s\n", buf);
|
nuclear@8
|
311 }
|
nuclear@8
|
312 }
|
nuclear@8
|
313
|
nuclear@8
|
314 if(status) {
|
nuclear@8
|
315 must_link = false;
|
nuclear@8
|
316 //cache_state_uniforms();
|
nuclear@8
|
317 return true;
|
nuclear@8
|
318 }
|
nuclear@8
|
319 return false;
|
nuclear@8
|
320 }
|
nuclear@8
|
321
|
nuclear@8
|
322 void ShaderProg::bind() const
|
nuclear@8
|
323 {
|
nuclear@8
|
324 if(must_link) {
|
nuclear@8
|
325 if(!link()) {
|
nuclear@8
|
326 return;
|
nuclear@8
|
327 }
|
nuclear@8
|
328 }
|
nuclear@8
|
329 glUseProgram(prog);
|
nuclear@8
|
330 ShaderProg::current = (ShaderProg*)this;
|
nuclear@8
|
331
|
nuclear@8
|
332 //setup_state_uniforms();
|
nuclear@8
|
333 }
|
nuclear@8
|
334
|
nuclear@8
|
335
|
nuclear@8
|
336 int ShaderProg::get_attrib_location(const char *name) const
|
nuclear@8
|
337 {
|
nuclear@8
|
338 glUseProgram(prog);
|
nuclear@8
|
339 return glGetAttribLocation(prog, name);
|
nuclear@8
|
340 }
|
nuclear@8
|
341
|
nuclear@8
|
342 void ShaderProg::set_attrib_location(const char *name, int loc) const
|
nuclear@8
|
343 {
|
nuclear@8
|
344 glBindAttribLocation(prog, loc, name);
|
nuclear@8
|
345 must_link = true;
|
nuclear@8
|
346 }
|
nuclear@8
|
347
|
nuclear@8
|
348 int ShaderProg::get_uniform_location(const char *name) const
|
nuclear@8
|
349 {
|
nuclear@8
|
350 glUseProgram(prog);
|
nuclear@8
|
351 return glGetUniformLocation(prog, name);
|
nuclear@8
|
352 }
|
nuclear@8
|
353
|
nuclear@8
|
354 bool ShaderProg::set_uniform(int loc, int val) const
|
nuclear@8
|
355 {
|
nuclear@8
|
356 glUseProgram(prog);
|
nuclear@8
|
357 if(loc >= 0) {
|
nuclear@8
|
358 glUniform1i(loc, val);
|
nuclear@8
|
359 return true;
|
nuclear@8
|
360 }
|
nuclear@8
|
361 return false;
|
nuclear@8
|
362 }
|
nuclear@8
|
363
|
nuclear@8
|
364 bool ShaderProg::set_uniform(int loc, float val) const
|
nuclear@8
|
365 {
|
nuclear@8
|
366 glUseProgram(prog);
|
nuclear@8
|
367 if(loc >= 0) {
|
nuclear@8
|
368 glUniform1f(loc, val);
|
nuclear@8
|
369 return true;
|
nuclear@8
|
370 }
|
nuclear@8
|
371 return false;
|
nuclear@8
|
372 }
|
nuclear@8
|
373
|
nuclear@8
|
374 bool ShaderProg::set_uniform(int loc, const Vector2 &v) const
|
nuclear@8
|
375 {
|
nuclear@8
|
376 glUseProgram(prog);
|
nuclear@8
|
377 if(loc >= 0) {
|
nuclear@8
|
378 glUniform2f(loc, v.x, v.y);
|
nuclear@8
|
379 return true;
|
nuclear@8
|
380 }
|
nuclear@8
|
381 return false;
|
nuclear@8
|
382 }
|
nuclear@8
|
383
|
nuclear@8
|
384 bool ShaderProg::set_uniform(int loc, const Vector3 &v) const
|
nuclear@8
|
385 {
|
nuclear@8
|
386 glUseProgram(prog);
|
nuclear@8
|
387 if(loc >= 0) {
|
nuclear@8
|
388 glUniform3f(loc, v.x, v.y, v.z);
|
nuclear@8
|
389 return true;
|
nuclear@8
|
390 }
|
nuclear@8
|
391 return false;
|
nuclear@8
|
392 }
|
nuclear@8
|
393
|
nuclear@8
|
394 bool ShaderProg::set_uniform(int loc, const Vector4 &v) const
|
nuclear@8
|
395 {
|
nuclear@8
|
396 glUseProgram(prog);
|
nuclear@8
|
397 if(loc >= 0) {
|
nuclear@8
|
398 glUniform4f(loc, v.x, v.y, v.z, v.w);
|
nuclear@8
|
399 return true;
|
nuclear@8
|
400 }
|
nuclear@8
|
401 return false;
|
nuclear@8
|
402 }
|
nuclear@8
|
403
|
nuclear@8
|
404 bool ShaderProg::set_uniform(int loc, const Matrix3x3 &m) const
|
nuclear@8
|
405 {
|
nuclear@8
|
406 glUseProgram(prog);
|
nuclear@8
|
407 if(loc >= 0) {
|
nuclear@8
|
408 glUniformMatrix3fv(loc, 1, GL_TRUE, m[0]);
|
nuclear@8
|
409 return true;
|
nuclear@8
|
410 }
|
nuclear@8
|
411 return false;
|
nuclear@8
|
412 }
|
nuclear@8
|
413
|
nuclear@8
|
414 bool ShaderProg::set_uniform(int loc, const Matrix4x4 &m) const
|
nuclear@8
|
415 {
|
nuclear@8
|
416 glUseProgram(prog);
|
nuclear@8
|
417 if(loc >= 0) {
|
nuclear@8
|
418 glUniformMatrix4fv(loc, 1, GL_TRUE, m[0]);
|
nuclear@8
|
419 return true;
|
nuclear@8
|
420 }
|
nuclear@8
|
421 return false;
|
nuclear@8
|
422 }
|
nuclear@8
|
423
|
nuclear@8
|
424
|
nuclear@8
|
425 bool ShaderProg::set_uniform(const char *name, int val) const
|
nuclear@8
|
426 {
|
nuclear@8
|
427 return set_uniform(get_uniform_location(name), val);
|
nuclear@8
|
428 }
|
nuclear@8
|
429
|
nuclear@8
|
430 bool ShaderProg::set_uniform(const char *name, float val) const
|
nuclear@8
|
431 {
|
nuclear@8
|
432 return set_uniform(get_uniform_location(name), val);
|
nuclear@8
|
433 }
|
nuclear@8
|
434
|
nuclear@8
|
435 bool ShaderProg::set_uniform(const char *name, const Vector2 &v) const
|
nuclear@8
|
436 {
|
nuclear@8
|
437 return set_uniform(get_uniform_location(name), v);
|
nuclear@8
|
438 }
|
nuclear@8
|
439
|
nuclear@8
|
440 bool ShaderProg::set_uniform(const char *name, const Vector3 &v) const
|
nuclear@8
|
441 {
|
nuclear@8
|
442 return set_uniform(get_uniform_location(name), v);
|
nuclear@8
|
443 }
|
nuclear@8
|
444
|
nuclear@8
|
445 bool ShaderProg::set_uniform(const char *name, const Vector4 &v) const
|
nuclear@8
|
446 {
|
nuclear@8
|
447 return set_uniform(get_uniform_location(name), v);
|
nuclear@8
|
448 }
|
nuclear@8
|
449
|
nuclear@8
|
450 bool ShaderProg::set_uniform(const char *name, const Matrix3x3 &m) const
|
nuclear@8
|
451 {
|
nuclear@8
|
452 return set_uniform(get_uniform_location(name), m);
|
nuclear@8
|
453 }
|
nuclear@8
|
454
|
nuclear@8
|
455 bool ShaderProg::set_uniform(const char *name, const Matrix4x4 &m) const
|
nuclear@8
|
456 {
|
nuclear@8
|
457 return set_uniform(get_uniform_location(name), m);
|
nuclear@8
|
458 }
|
nuclear@8
|
459
|
nuclear@8
|
460 /*
|
nuclear@8
|
461 static StType unist_type(GLenum type)
|
nuclear@8
|
462 {
|
nuclear@8
|
463 switch(type) {
|
nuclear@8
|
464 case GL_FLOAT:
|
nuclear@8
|
465 return ST_FLOAT;
|
nuclear@8
|
466 case GL_FLOAT_VEC2:
|
nuclear@8
|
467 return ST_FLOAT2;
|
nuclear@8
|
468 case GL_FLOAT_VEC3:
|
nuclear@8
|
469 return ST_FLOAT3;
|
nuclear@8
|
470 case GL_FLOAT_VEC4:
|
nuclear@8
|
471 return ST_FLOAT4;
|
nuclear@8
|
472 case GL_INT:
|
nuclear@8
|
473 case GL_SAMPLER_2D:
|
nuclear@8
|
474 case GL_SAMPLER_CUBE:
|
nuclear@8
|
475 #if !GL_ES_VERSION_2_0
|
nuclear@8
|
476 case GL_SAMPLER_1D:
|
nuclear@8
|
477 case GL_SAMPLER_3D:
|
nuclear@8
|
478 case GL_SAMPLER_1D_SHADOW:
|
nuclear@8
|
479 case GL_SAMPLER_2D_SHADOW:
|
nuclear@8
|
480 #endif
|
nuclear@8
|
481 return ST_INT;
|
nuclear@8
|
482 case GL_INT_VEC2:
|
nuclear@8
|
483 return ST_INT2;
|
nuclear@8
|
484 case GL_INT_VEC3:
|
nuclear@8
|
485 return ST_INT3;
|
nuclear@8
|
486 case GL_INT_VEC4:
|
nuclear@8
|
487 return ST_INT4;
|
nuclear@8
|
488 case GL_FLOAT_MAT3:
|
nuclear@8
|
489 return ST_MATRIX3;
|
nuclear@8
|
490 case GL_FLOAT_MAT4:
|
nuclear@8
|
491 return ST_MATRIX4;
|
nuclear@8
|
492 default:
|
nuclear@8
|
493 break;
|
nuclear@8
|
494 }
|
nuclear@8
|
495 return ST_UNKNOWN;
|
nuclear@8
|
496 }
|
nuclear@8
|
497
|
nuclear@8
|
498 void ShaderProg::cache_state_uniforms() const
|
nuclear@8
|
499 {
|
nuclear@8
|
500 if(!glIsProgram(prog)) {
|
nuclear@8
|
501 return;
|
nuclear@8
|
502 }
|
nuclear@8
|
503
|
nuclear@8
|
504 int num_uni;
|
nuclear@8
|
505 glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_uni);
|
nuclear@8
|
506
|
nuclear@8
|
507 char name[256];
|
nuclear@8
|
508 for(int i=0; i<num_uni; i++) {
|
nuclear@8
|
509 GLint sz;
|
nuclear@8
|
510 GLenum type;
|
nuclear@8
|
511 glGetActiveUniform(prog, i, sizeof name - 1, 0, &sz, &type, name);
|
nuclear@8
|
512
|
nuclear@8
|
513 if(strstr(name, "st_") == name) {
|
nuclear@8
|
514 StateLocCache s;
|
nuclear@8
|
515 s.sidx = add_unistate(name, unist_type(type));
|
nuclear@8
|
516 s.loc = glGetUniformLocation(prog, name);
|
nuclear@8
|
517 stloc_cache.push_back(s);
|
nuclear@8
|
518 }
|
nuclear@8
|
519 }
|
nuclear@8
|
520 }
|
nuclear@8
|
521
|
nuclear@8
|
522 void ShaderProg::setup_state_uniforms() const
|
nuclear@8
|
523 {
|
nuclear@8
|
524 for(size_t i=0; i<stloc_cache.size(); i++) {
|
nuclear@8
|
525 setup_unistate(stloc_cache[i].sidx, this, stloc_cache[i].loc);
|
nuclear@8
|
526 }
|
nuclear@8
|
527 }
|
nuclear@8
|
528 */
|
nuclear@8
|
529
|
nuclear@8
|
530 // Static functions to use with ShaderSet
|
nuclear@8
|
531 Shader *Shader::create_shader()
|
nuclear@8
|
532 {
|
nuclear@8
|
533 return new Shader;
|
nuclear@8
|
534 }
|
nuclear@8
|
535
|
nuclear@8
|
536 bool Shader::load_shader(Shader *sdr, const char *fname)
|
nuclear@8
|
537 {
|
nuclear@8
|
538 std::string src = read_source(fname);
|
nuclear@8
|
539 if(src.empty()) {
|
nuclear@8
|
540 return false;
|
nuclear@8
|
541 }
|
nuclear@8
|
542
|
nuclear@8
|
543 sdr->src = src;
|
nuclear@8
|
544 return true;
|
nuclear@8
|
545 }
|
nuclear@8
|
546
|
nuclear@8
|
547 bool Shader::done_shader(Shader *sdr, unsigned int type)
|
nuclear@8
|
548 {
|
nuclear@8
|
549 return sdr->create(sdr->src.c_str(), type);
|
nuclear@8
|
550 }
|
nuclear@8
|
551
|
nuclear@8
|
552 /*
|
nuclear@8
|
553 static bool done_vertex_shader(Shader *sdr)
|
nuclear@8
|
554 {
|
nuclear@8
|
555 return Shader::done_shader(sdr, GL_VERTEX_SHADER);
|
nuclear@8
|
556 }
|
nuclear@8
|
557
|
nuclear@8
|
558 static bool done_pixel_shader(Shader *sdr)
|
nuclear@8
|
559 {
|
nuclear@8
|
560 return Shader::done_shader(sdr, GL_FRAGMENT_SHADER);
|
nuclear@8
|
561 }
|
nuclear@8
|
562
|
nuclear@8
|
563 #ifdef HAVE_GEOMETRY_SHADER
|
nuclear@8
|
564 static bool done_geom_shader(Shader *sdr)
|
nuclear@8
|
565 {
|
nuclear@8
|
566 return Shader::done_shader(sdr, GL_GEOMETRY_SHADER);
|
nuclear@8
|
567 }
|
nuclear@8
|
568 #endif
|
nuclear@8
|
569
|
nuclear@8
|
570 #ifdef HAVE_TESSELATION_SHADER
|
nuclear@8
|
571 static bool done_tc_shader(Shader *sdr)
|
nuclear@8
|
572 {
|
nuclear@8
|
573 return Shader::done_shader(sdr, GL_TESS_CONTROL_SHADER);
|
nuclear@8
|
574 }
|
nuclear@8
|
575
|
nuclear@8
|
576 static bool done_te_shader(Shader *sdr)
|
nuclear@8
|
577 {
|
nuclear@8
|
578 return Shader::done_shader(sdr, GL_TESS_EVALUATION_SHADER);
|
nuclear@8
|
579 }
|
nuclear@8
|
580 #endif
|
nuclear@8
|
581
|
nuclear@8
|
582 void Shader::destroy_shader(Shader *sdr)
|
nuclear@8
|
583 {
|
nuclear@8
|
584 delete sdr;
|
nuclear@8
|
585 }
|
nuclear@8
|
586
|
nuclear@8
|
587 // ---- ShaderSet ----
|
nuclear@8
|
588
|
nuclear@8
|
589 ShaderSet::ShaderSet(unsigned int type)
|
nuclear@8
|
590 : DataSet<Shader*>(Shader::create_shader, Shader::load_shader, 0, Shader::destroy_shader)
|
nuclear@8
|
591 {
|
nuclear@8
|
592 switch(type) {
|
nuclear@8
|
593 case GL_VERTEX_SHADER:
|
nuclear@8
|
594 done = done_vertex_shader;
|
nuclear@8
|
595 break;
|
nuclear@8
|
596
|
nuclear@8
|
597 case GL_FRAGMENT_SHADER:
|
nuclear@8
|
598 done = done_pixel_shader;
|
nuclear@8
|
599 break;
|
nuclear@8
|
600
|
nuclear@8
|
601 #ifdef HAVE_GEOMETRY_SHADER
|
nuclear@8
|
602 case GL_GEOMETRY_SHADER:
|
nuclear@8
|
603 done = done_geom_shader;
|
nuclear@8
|
604 break;
|
nuclear@8
|
605 #endif
|
nuclear@8
|
606
|
nuclear@8
|
607 #ifdef HAVE_TESSELATION_SHADER
|
nuclear@8
|
608 case GL_TESS_CONTROL_SHADER:
|
nuclear@8
|
609 done = done_tc_shader;
|
nuclear@8
|
610 break;
|
nuclear@8
|
611
|
nuclear@8
|
612 case GL_TESS_EVALUATION_SHADER:
|
nuclear@8
|
613 done = done_te_shader;
|
nuclear@8
|
614 break;
|
nuclear@8
|
615 #endif
|
nuclear@8
|
616
|
nuclear@8
|
617 default:
|
nuclear@8
|
618 fprintf(stderr, "ShaderSet constructed with invalid shader type!\n");
|
nuclear@8
|
619 }
|
nuclear@8
|
620 }
|
nuclear@8
|
621 */
|
nuclear@8
|
622
|
nuclear@8
|
623 static struct { const char *name; int loc; } attr_loc[] = {
|
nuclear@8
|
624 {"attr_vertex", MESH_ATTR_VERTEX},
|
nuclear@8
|
625 {"attr_normal", MESH_ATTR_NORMAL},
|
nuclear@8
|
626 {"attr_tangent", MESH_ATTR_TANGENT},
|
nuclear@8
|
627 {"attr_texcoord", MESH_ATTR_TEXCOORD},
|
nuclear@8
|
628 {"attr_color", MESH_ATTR_COLOR},
|
nuclear@8
|
629 {"attr_boneweights", MESH_ATTR_BONEWEIGHTS},
|
nuclear@8
|
630 {"attr_boneidx", MESH_ATTR_BONEIDX}
|
nuclear@8
|
631 };
|
nuclear@8
|
632
|
nuclear@8
|
633 static void bind_standard_attr(const ShaderProg *prog)
|
nuclear@8
|
634 {
|
nuclear@8
|
635 // we must link once to find out which are the active attributes
|
nuclear@8
|
636 glLinkProgram(prog->get_id());
|
nuclear@8
|
637
|
nuclear@8
|
638 int num_attr;
|
nuclear@8
|
639 glGetProgramiv(prog->get_id(), GL_ACTIVE_ATTRIBUTES, &num_attr);
|
nuclear@8
|
640
|
nuclear@8
|
641 char name[256];
|
nuclear@8
|
642 for(int i=0; i<num_attr; i++) {
|
nuclear@8
|
643 GLint sz;
|
nuclear@8
|
644 GLenum type;
|
nuclear@8
|
645 glGetActiveAttrib(prog->get_id(), i, sizeof name - 1, 0, &sz, &type, name);
|
nuclear@8
|
646
|
nuclear@8
|
647 for(int j=0; j<(int)(sizeof attr_loc / sizeof *attr_loc); j++) {
|
nuclear@8
|
648 if(strcmp(name, attr_loc[j].name) == 0) {
|
nuclear@8
|
649 prog->set_attrib_location(name, attr_loc[j].loc);
|
nuclear@8
|
650 }
|
nuclear@8
|
651 }
|
nuclear@8
|
652 }
|
nuclear@8
|
653 }
|
nuclear@8
|
654
|
nuclear@8
|
655
|
nuclear@8
|
656 /*
|
nuclear@8
|
657 static const char *strtype(unsigned int type)
|
nuclear@8
|
658 {
|
nuclear@8
|
659 switch(type) {
|
nuclear@8
|
660 case GL_VERTEX_SHADER:
|
nuclear@8
|
661 return "vertex";
|
nuclear@8
|
662 case GL_FRAGMENT_SHADER:
|
nuclear@8
|
663 return "fragment";
|
nuclear@8
|
664 #ifdef HAVE_GEOMETRY_SHADER
|
nuclear@8
|
665 case GL_GEOMETRY_SHADER:
|
nuclear@8
|
666 return "geometry";
|
nuclear@8
|
667 #endif
|
nuclear@8
|
668 #ifdef HAVE_TESSELATION_SHADER
|
nuclear@8
|
669 case GL_TESS_CONTROL_SHADER:
|
nuclear@8
|
670 return "tesselation control";
|
nuclear@8
|
671 case GL_TESS_EVALUATION_SHADER:
|
nuclear@8
|
672 return "tesselation evaluation";
|
nuclear@8
|
673 #endif
|
nuclear@8
|
674 default:
|
nuclear@8
|
675 break;
|
nuclear@8
|
676 }
|
nuclear@8
|
677 return "<unknown>";
|
nuclear@8
|
678 }
|
nuclear@8
|
679 */
|