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