~ubuntu-branches/debian/wheezy/gource/wheezy

« back to all changes in this revision

Viewing changes to src/core/shader.cpp

  • Committer: Package Import Robot
  • Author(s): Andrew Caudwell
  • Date: 2012-04-24 11:25:45 UTC
  • mfrom: (1.2.13)
  • Revision ID: package-import@ubuntu.com-20120424112545-18fbnycu9xrsl4s5
Tags: 0.38-1
* New upstream release (closes: #667189)
* New build dependencies on libglm-dev and libboost-filesystem-dev. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
 
32
32
//ShaderManager
33
33
 
34
 
Regex Shader_pre_include("\\s*#include\\s*\"([^\"]+)\"");
 
34
ShaderManager::ShaderManager() {
 
35
    warnings = false;
 
36
}
 
37
 
 
38
void ShaderManager::enableWarnings(bool warnings) {
 
39
    this->warnings = warnings;
 
40
}
 
41
 
 
42
Regex Shader_pre_version("^\\s*#version\\s*(\\d+)\\s*$");
 
43
Regex Shader_pre_extension("^\\s*#extension\\s*([a-zA-Z0-9_]+)\\s+:\\s+(enable|require|warn|disable)\\s*$");
 
44
Regex Shader_pre_include("^\\s*#include\\s*\"([^\"]+)\"");
 
45
Regex Shader_uniform_def("^\\s*uniform\\s+(\\w+)\\s+(\\w+)(?:\\[(\\d+)\\])?\\s*;\\s*$");
 
46
Regex Shader_error_line("\\b\\d*\\((\\d+)\\) : error ");
 
47
Regex Shader_error2_line("\\bERROR: \\d+:(\\d+):");
 
48
Regex Shader_warning_line("\\b\\d*\\((\\d+)\\) : warning ");
35
49
 
36
50
Shader* ShaderManager::grab(const std::string& shader_prefix) {
37
51
    Resource* s = resources[shader_prefix];
46
60
    return (Shader*) s;
47
61
}
48
62
 
49
 
//Shader
50
 
Shader::Shader(const std::string& prefix) : Resource(prefix) {
51
 
 
52
 
    std::string shader_dir = shadermanager.getDir();
53
 
 
54
 
    std::string vertexSrc   = shader_dir + prefix + std::string(".vert");
55
 
    std::string fragmentSrc = shader_dir + prefix + std::string(".frag");
56
 
 
57
 
    vertexShader   = load(vertexSrc,   GL_VERTEX_SHADER);
58
 
    fragmentShader = load(fragmentSrc, GL_FRAGMENT_SHADER);
59
 
 
60
 
    makeProgram();
61
 
}
62
 
 
63
 
Shader::~Shader() {
64
 
    glDeleteShader(vertexShader);
65
 
    glDeleteShader(fragmentShader);
66
 
    glDeleteProgram(shaderProg);
67
 
}
68
 
 
69
 
void Shader::makeProgram() {
70
 
    shaderProg = glCreateProgram();
71
 
    glAttachShader(shaderProg,fragmentShader);
72
 
    glAttachShader(shaderProg,vertexShader);
73
 
    glLinkProgram(shaderProg);
74
 
}
75
 
 
76
 
void Shader::checkError(const std::string& filename, GLenum shaderRef) {
77
 
 
78
 
    GLint compile_success;   
79
 
    glGetShaderiv(shaderRef, GL_COMPILE_STATUS, &compile_success);
 
63
void ShaderManager::manage(Shader* shader) {
 
64
 
 
65
    if(shader->resource_name.empty()) {
 
66
        throw SDLAppException("Cannot manage shader with no resource name");
 
67
    }
 
68
 
 
69
    if(resources[shader->resource_name] != 0) {
 
70
        throw SDLAppException("A shader resource already exists under the name '%s'", shader->resource_name.c_str());
 
71
    }
 
72
 
 
73
    resources[shader->resource_name] = shader;
 
74
 
 
75
    shader->addref();
 
76
}
 
77
 
 
78
void ShaderManager::unload() {
 
79
    for(std::map<std::string, Resource*>::iterator it= resources.begin(); it!=resources.end();it++) {
 
80
        ((Shader*)it->second)->unload();
 
81
    }
 
82
}
 
83
 
 
84
void ShaderManager::reload() {
 
85
    for(std::map<std::string, Resource*>::iterator it= resources.begin(); it!=resources.end();it++) {
 
86
        ((Shader*)it->second)->load();
 
87
    }
 
88
}
 
89
 
 
90
//ShaderUniform
 
91
 
 
92
ShaderUniform::ShaderUniform(Shader* shader, const std::string& name, int uniform_type, const std::string& type_name)
 
93
    : shader(shader), name(name), location(-1), initialized(false), modified(false), baked(false), uniform_type(uniform_type), type_name(type_name) {
 
94
}
 
95
 
 
96
void ShaderUniform::unload() {
 
97
    location = -1;
 
98
}
 
99
 
 
100
const std::string& ShaderUniform::getName() const {
 
101
    return name;
 
102
}
 
103
 
 
104
GLint ShaderUniform::getLocation() {
 
105
 
 
106
    // TODO: (re-)compiling the shader should break the uniform location caching.
 
107
 
 
108
    if(location != -1) return location;
 
109
 
 
110
    location = glGetUniformLocation( shader->getProgram(), name.c_str() );
 
111
 
 
112
    return location;
 
113
}
 
114
 
 
115
void ShaderUniform::setBaked(bool baked) {
 
116
    if(this->baked == baked) return;
 
117
    this->baked = baked;
 
118
    modified = true;
 
119
}
 
120
 
 
121
 
 
122
//FloatShaderUniform
 
123
 
 
124
FloatShaderUniform::FloatShaderUniform(Shader* shader, const std::string& name, float value) :
 
125
    value(value), ShaderUniform(shader, name, SHADER_UNIFORM_FLOAT, "float") {
 
126
}
 
127
 
 
128
void FloatShaderUniform::setValue(float value) {
 
129
    if(baked && this->value == value) return;
 
130
 
 
131
    this->value = value;
 
132
    modified = true;
 
133
    initialized = true;
 
134
}
 
135
 
 
136
void FloatShaderUniform::apply() {
 
137
    glUniform1f(getLocation(), value);
 
138
}
 
139
 
 
140
float FloatShaderUniform::getValue() const {
 
141
    return value;
 
142
}
 
143
 
 
144
void FloatShaderUniform::write(std::string& content) const {
 
145
 
 
146
    char buff[256];
 
147
 
 
148
    if(baked) {
 
149
//        snprintf(buff, 256, "const %s %s = %e;\n", type_name.c_str(), name.c_str(), value);
 
150
        snprintf(buff, 256, "#define %s %e\n", name.c_str(), value);
 
151
    } else {
 
152
        snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
 
153
    }
 
154
 
 
155
    content += buff;
 
156
}
 
157
 
 
158
//IntShaderUniform
 
159
 
 
160
IntShaderUniform::IntShaderUniform(Shader* shader, const std::string& name, int value) :
 
161
    value(value), ShaderUniform(shader, name, SHADER_UNIFORM_INT, "int") {
 
162
}
 
163
 
 
164
void IntShaderUniform::setValue(int value) {
 
165
    if(baked && this->value == value) return;
 
166
 
 
167
    this->value = value;
 
168
    modified = true;
 
169
    initialized = true;
 
170
}
 
171
 
 
172
void IntShaderUniform::apply() {
 
173
    glUniform1i(getLocation(), value);
 
174
}
 
175
 
 
176
float IntShaderUniform::getValue() const {
 
177
    return value;
 
178
}
 
179
 
 
180
void IntShaderUniform::write(std::string& content) const {
 
181
 
 
182
    char buff[256];
 
183
 
 
184
    if(baked) {
 
185
        snprintf(buff, 256, "#define %s %d\n", name.c_str(), value);
 
186
    } else {
 
187
        snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
 
188
    }
 
189
 
 
190
    content += buff;
 
191
}
 
192
 
 
193
//BoolShaderUniform
 
194
 
 
195
BoolShaderUniform::BoolShaderUniform(Shader* shader, const std::string& name, bool value) :
 
196
    value(value), ShaderUniform(shader, name, SHADER_UNIFORM_BOOL, "bool") {
 
197
}
 
198
 
 
199
void BoolShaderUniform::setValue(bool value) {
 
200
    if(baked && this->value == value) return;
 
201
 
 
202
    this->value = value;
 
203
    modified = true;
 
204
    initialized = true;
 
205
}
 
206
 
 
207
void BoolShaderUniform::apply() {
 
208
    glUniform1i(getLocation(), value);
 
209
}
 
210
 
 
211
float BoolShaderUniform::getValue() const {
 
212
    return value;
 
213
}
 
214
 
 
215
void BoolShaderUniform::write(std::string& content) const {
 
216
 
 
217
    char buff[256];
 
218
 
 
219
    if(baked) {
 
220
        snprintf(buff, 256, "#define %s %s\n", name.c_str(), value ? "true" : "false");
 
221
    } else {
 
222
        snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
 
223
    }
 
224
 
 
225
    content += buff;
 
226
}
 
227
 
 
228
//Sampler1DShaderUniform
 
229
 
 
230
Sampler1DShaderUniform::Sampler1DShaderUniform(Shader* shader, const std::string& name, int value) :
 
231
    value(value), ShaderUniform(shader, name, SHADER_UNIFORM_SAMPLER_1D, "sampler1D") {
 
232
}
 
233
 
 
234
void Sampler1DShaderUniform::setValue(int value) {
 
235
    if(baked && this->value == value) return;
 
236
 
 
237
    this->value = value;
 
238
    modified = true;
 
239
    initialized = true;
 
240
}
 
241
 
 
242
void Sampler1DShaderUniform::setBaked(bool baked) {
 
243
}
 
244
 
 
245
void Sampler1DShaderUniform::write(std::string& content) const {
 
246
    char buff[256];
 
247
    snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
 
248
    content += buff;
 
249
}
 
250
 
 
251
void Sampler1DShaderUniform::apply() {
 
252
    glUniform1i(getLocation(), value);
 
253
}
 
254
 
 
255
float Sampler1DShaderUniform::getValue() const {
 
256
    return value;
 
257
}
 
258
 
 
259
//Sampler2DShaderUniform
 
260
 
 
261
Sampler2DShaderUniform::Sampler2DShaderUniform(Shader* shader, const std::string& name, int value) :
 
262
    value(value), ShaderUniform(shader, name, SHADER_UNIFORM_SAMPLER_2D, "sampler2D") {
 
263
}
 
264
 
 
265
void Sampler2DShaderUniform::setValue(int value) {
 
266
    if(baked && this->value == value) return;
 
267
 
 
268
    this->value = value;
 
269
    modified = true;
 
270
    initialized = true;
 
271
}
 
272
 
 
273
void Sampler2DShaderUniform::apply() {
 
274
    glUniform1i(getLocation(), value);
 
275
}
 
276
 
 
277
float Sampler2DShaderUniform::getValue() const {
 
278
    return value;
 
279
}
 
280
 
 
281
//cant be baked
 
282
void Sampler2DShaderUniform::setBaked(bool baked) {
 
283
}
 
284
 
 
285
void Sampler2DShaderUniform::write(std::string& content) const {
 
286
    char buff[256];
 
287
    snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
 
288
    content += buff;
 
289
}
 
290
 
 
291
 
 
292
//Vec2ShaderUniform
 
293
 
 
294
Vec2ShaderUniform::Vec2ShaderUniform(Shader* shader, const std::string& name, const vec2& value) :
 
295
    value(value), ShaderUniform(shader, name, SHADER_UNIFORM_VEC2, "vec2") {
 
296
}
 
297
 
 
298
void Vec2ShaderUniform::setValue(const vec2& value) {
 
299
    if(baked && this->value == value) return;
 
300
 
 
301
    this->value = value;
 
302
    modified = true;
 
303
    initialized = true;
 
304
}
 
305
 
 
306
void Vec2ShaderUniform::apply() {
 
307
    glUniform2fv(getLocation(), 1, glm::value_ptr(value));
 
308
}
 
309
 
 
310
const vec2& Vec2ShaderUniform::getValue() const {
 
311
    return value;
 
312
}
 
313
 
 
314
void Vec2ShaderUniform::write(std::string& content) const {
 
315
 
 
316
    char buff[256];
 
317
 
 
318
    if(baked) {
 
319
        snprintf(buff, 256, "#define %s vec2(%e, %e)\n", name.c_str(), value.x, value.y);
 
320
    } else {
 
321
        snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
 
322
    }
 
323
 
 
324
    content += buff;
 
325
}
 
326
 
 
327
//Vec3ShaderUniform
 
328
 
 
329
Vec3ShaderUniform::Vec3ShaderUniform(Shader* shader, const std::string& name, const vec3& value) :
 
330
    value(value), ShaderUniform(shader, name, SHADER_UNIFORM_VEC3, "vec3") {
 
331
}
 
332
 
 
333
 
 
334
void Vec3ShaderUniform::setValue(const vec3& value) {
 
335
    if(baked && this->value == value) return;
 
336
 
 
337
    this->value = value;
 
338
    modified = true;
 
339
    initialized = true;
 
340
}
 
341
 
 
342
void Vec3ShaderUniform::apply() {
 
343
    glUniform3fv(getLocation(), 1, glm::value_ptr(value));
 
344
}
 
345
 
 
346
 
 
347
const vec3& Vec3ShaderUniform::getValue() const {
 
348
    return value;
 
349
}
 
350
 
 
351
void Vec3ShaderUniform::write(std::string& content) const {
 
352
 
 
353
    char buff[256];
 
354
 
 
355
    if(baked) {
 
356
        snprintf(buff, 256, "#define %s vec3(%e, %e, %e)\n", name.c_str(), value.x, value.y, value.z);
 
357
    } else {
 
358
        snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
 
359
    }
 
360
 
 
361
    content += buff;
 
362
}
 
363
 
 
364
//Vec4ShaderUniform
 
365
 
 
366
Vec4ShaderUniform::Vec4ShaderUniform(Shader* shader, const std::string& name, const vec4& value) :
 
367
    value(value), ShaderUniform(shader, name, SHADER_UNIFORM_VEC4, "vec4") {
 
368
}
 
369
 
 
370
void Vec4ShaderUniform::setValue(const vec4& value) {
 
371
    if(baked && this->value == value) return;
 
372
 
 
373
    this->value = value;
 
374
    modified = true;
 
375
    initialized = true;
 
376
}
 
377
 
 
378
void Vec4ShaderUniform::apply() {
 
379
    glUniform4fv(getLocation(), 1, glm::value_ptr(value));
 
380
}
 
381
 
 
382
const vec4& Vec4ShaderUniform::getValue() const {
 
383
    return value;
 
384
}
 
385
 
 
386
void Vec4ShaderUniform::write(std::string& content) const {
 
387
 
 
388
    char buff[256];
 
389
 
 
390
    if(baked) {
 
391
        snprintf(buff, 256, "#define %s vec4(%e, %e, %e, %e)\n", name.c_str(), value.x, value.y, value.z, value.w);
 
392
    } else {
 
393
        snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
 
394
    }
 
395
 
 
396
    content += buff;
 
397
}
 
398
 
 
399
//Mat3ShaderUniform
 
400
 
 
401
Mat3ShaderUniform::Mat3ShaderUniform(Shader* shader, const std::string& name, const mat3& value) :
 
402
    value(value), ShaderUniform(shader, name, SHADER_UNIFORM_MAT3, "mat3") {
 
403
}
 
404
 
 
405
void Mat3ShaderUniform::setValue(const mat3& value) {
 
406
    if(baked && this->value == value) return;
 
407
 
 
408
    this->value = value;
 
409
    modified = true;
 
410
    initialized = true;
 
411
}
 
412
 
 
413
void Mat3ShaderUniform::apply() {
 
414
    glUniformMatrix3fv(getLocation(), 1, 0, glm::value_ptr(value));
 
415
}
 
416
 
 
417
const mat3& Mat3ShaderUniform::getValue() const {
 
418
    return value;
 
419
}
 
420
 
 
421
void Mat3ShaderUniform::write(std::string& content) const {
 
422
 
 
423
    char buff[1024];
 
424
 
 
425
    if(baked) {
 
426
        snprintf(buff, 1024, "#define %s mat3(%e, %e, %e, %e, %e, %e, %e, %e, %e)\n", name.c_str(),
 
427
                value[0][0], value[0][1], value[0][2],
 
428
                value[1][0], value[1][1], value[1][2],
 
429
                value[2][0], value[2][1], value[2][2]);
 
430
 
 
431
    } else {
 
432
        snprintf(buff, 1024, "uniform %s %s;\n", type_name.c_str(), name.c_str());
 
433
    }
 
434
 
 
435
    content += buff;
 
436
}
 
437
 
 
438
//Mat4ShaderUniform
 
439
 
 
440
Mat4ShaderUniform::Mat4ShaderUniform(Shader* shader, const std::string& name, const mat4& value) :
 
441
    value(value), ShaderUniform(shader, name, SHADER_UNIFORM_MAT4, "mat4") {
 
442
}
 
443
 
 
444
void Mat4ShaderUniform::setValue(const mat4& value) {
 
445
    if(baked && this->value == value) return;
 
446
 
 
447
    this->value = value;
 
448
    modified = true;
 
449
    initialized = true;
 
450
}
 
451
 
 
452
void Mat4ShaderUniform::apply() {
 
453
    glUniformMatrix4fv(getLocation(), 1, 0, glm::value_ptr(value));
 
454
}
 
455
 
 
456
const mat4& Mat4ShaderUniform::getValue() const {
 
457
    return value;
 
458
}
 
459
 
 
460
void Mat4ShaderUniform::write(std::string& content) const {
 
461
 
 
462
    char buff[1024];
 
463
 
 
464
    if(baked) {
 
465
        snprintf(buff, 1024, "#define %s mat4(%e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e)\n", name.c_str(),
 
466
                value[0][0], value[0][1], value[0][2], value[0][3],
 
467
                value[1][0], value[1][1], value[1][2], value[1][3],
 
468
                value[2][0], value[2][1], value[2][2], value[2][3],
 
469
                value[3][0], value[3][1], value[3][2], value[3][3]);
 
470
    } else {
 
471
        snprintf(buff, 1024, "uniform %s %s;\n", type_name.c_str(), name.c_str());
 
472
    }
 
473
 
 
474
    content += buff;
 
475
}
 
476
 
 
477
 
 
478
//Vec2ArrayShaderUniform
 
479
 
 
480
Vec2ArrayShaderUniform::Vec2ArrayShaderUniform(Shader* shader, const std::string& name, size_t length, const vec2* value) :
 
481
    length(length), ShaderUniform(shader, name, SHADER_UNIFORM_VEC2_ARRAY, "vec2") {
 
482
    this->value = new vec2[length];
 
483
    if(value != 0) copyValue(value);
 
484
}
 
485
 
 
486
Vec2ArrayShaderUniform::~Vec2ArrayShaderUniform() {
 
487
    if(value) delete[] value;
 
488
}
 
489
 
 
490
const vec2* Vec2ArrayShaderUniform::getValue() const {
 
491
    return value;
 
492
}
 
493
 
 
494
void Vec2ArrayShaderUniform::copyValue(const vec2* value) {
 
495
    for(size_t i=0; i<length; i++) {
 
496
        this->value[i] = value[i];
 
497
    }
 
498
}
 
499
 
 
500
void Vec2ArrayShaderUniform::copyValue(const std::vector<vec2>& value) {
 
501
    for(size_t i=0; i<length; i++) {
 
502
        this->value[i] = value[i];
 
503
    }
 
504
}
 
505
 
 
506
void Vec2ArrayShaderUniform::setValue(const vec2* value) {
 
507
    if(baked) {
 
508
        bool match = true;
 
509
 
 
510
        for(size_t i=0;i<length;i++) {
 
511
            if(value[i] != this->value[i]) {
 
512
                match = false;
 
513
                break;
 
514
            }
 
515
        }
 
516
 
 
517
        if(match) return;
 
518
    }
 
519
 
 
520
    copyValue(value);
 
521
 
 
522
    modified = true;
 
523
    initialized = true;
 
524
}
 
525
 
 
526
void Vec2ArrayShaderUniform::setValue(const std::vector<vec2>& value) {
 
527
    if(baked) {
 
528
        bool match = true;
 
529
 
 
530
        for(size_t i=0;i<length;i++) {
 
531
            if(value[i] != this->value[i]) {
 
532
                match = false;
 
533
                break;
 
534
            }
 
535
        }
 
536
 
 
537
        if(match) return;
 
538
    }
 
539
 
 
540
    copyValue(value);
 
541
 
 
542
    modified = true;
 
543
    initialized = true;
 
544
}
 
545
 
 
546
void Vec2ArrayShaderUniform::apply() {
 
547
    glUniform2fv(getLocation(), length, glm::value_ptr(value[0]));
 
548
}
 
549
 
 
550
void Vec2ArrayShaderUniform::write(std::string& content) const {
 
551
 
 
552
    char buff[1024];
 
553
 
 
554
    if(baked) {
 
555
        snprintf(buff, 1024, "%s[%ld] %s = %s[] (\n", type_name.c_str(), length, name.c_str(), type_name.c_str());
 
556
 
 
557
        content += buff;
 
558
 
 
559
        for(size_t i=0; i<length; i++) {
 
560
            snprintf(buff, 1024, "    %s(%e, %e)", type_name.c_str(), value[i].x, value[i].y);
 
561
            content += buff;
 
562
            if(i<length-1) content += ",\n";
 
563
            else           content += "\n);\n";
 
564
        }
 
565
 
 
566
    } else {
 
567
        snprintf(buff, 1024, "uniform %s %s[%ld];\n", type_name.c_str(), name.c_str(), length);
 
568
        content += buff;
 
569
    }
 
570
}
 
571
 
 
572
//Vec3ArrayShaderUniform
 
573
 
 
574
Vec3ArrayShaderUniform::Vec3ArrayShaderUniform(Shader* shader, const std::string& name, size_t length, const vec3* value) :
 
575
    length(length), ShaderUniform(shader, name, SHADER_UNIFORM_VEC3_ARRAY, "vec3") {
 
576
    this->value = new vec3[length];
 
577
    if(value != 0) copyValue(value);
 
578
}
 
579
 
 
580
Vec3ArrayShaderUniform::~Vec3ArrayShaderUniform() {
 
581
    if(value) delete[] value;
 
582
}
 
583
 
 
584
const vec3* Vec3ArrayShaderUniform::getValue() const {
 
585
    return value;
 
586
}
 
587
 
 
588
void Vec3ArrayShaderUniform::copyValue(const vec3* value) {
 
589
    for(size_t i=0; i<length; i++) {
 
590
        this->value[i] = value[i];
 
591
    }
 
592
}
 
593
 
 
594
void Vec3ArrayShaderUniform::copyValue(const std::vector<vec3>& value) {
 
595
    for(size_t i=0; i<length; i++) {
 
596
        this->value[i] = value[i];
 
597
    }
 
598
}
 
599
 
 
600
void Vec3ArrayShaderUniform::setValue(const vec3* value) {
 
601
    if(baked) {
 
602
        bool match = true;
 
603
 
 
604
        for(size_t i=0;i<length;i++) {
 
605
            if(value[i] != this->value[i]) {
 
606
                match = false;
 
607
                break;
 
608
            }
 
609
        }
 
610
 
 
611
        if(match) return;
 
612
    }
 
613
 
 
614
    copyValue(value);
 
615
 
 
616
    modified = true;
 
617
    initialized = true;
 
618
}
 
619
 
 
620
void Vec3ArrayShaderUniform::setValue(const std::vector<vec3>& value) {
 
621
    if(baked) {
 
622
        bool match = true;
 
623
 
 
624
        for(size_t i=0;i<length;i++) {
 
625
            if(value[i] != this->value[i]) {
 
626
                match = false;
 
627
                break;
 
628
            }
 
629
        }
 
630
 
 
631
        if(match) return;
 
632
    }
 
633
 
 
634
    copyValue(value);
 
635
 
 
636
    modified = true;
 
637
    initialized = true;
 
638
}
 
639
 
 
640
void Vec3ArrayShaderUniform::apply() {
 
641
    glUniform3fv(getLocation(), length, glm::value_ptr(value[0]));
 
642
}
 
643
 
 
644
void Vec3ArrayShaderUniform::write(std::string& content) const {
 
645
 
 
646
    char buff[1024];
 
647
 
 
648
    if(baked) {
 
649
        snprintf(buff, 1024, "%s[%ld] %s = %s[] (\n", type_name.c_str(), length, name.c_str(), type_name.c_str());
 
650
 
 
651
        content += buff;
 
652
 
 
653
        for(size_t i=0; i<length; i++) {
 
654
            snprintf(buff, 1024, "    %s(%e, %e, %e)", type_name.c_str(), value[i].x, value[i].y, value[i].z);
 
655
            content += buff;
 
656
            if(i<length-1) content += ",\n";
 
657
            else           content += "\n);\n";
 
658
        }
 
659
 
 
660
    } else {
 
661
        snprintf(buff, 1024, "uniform %s %s[%ld];\n", type_name.c_str(), name.c_str(), length);
 
662
        content += buff;
 
663
    }
 
664
}
 
665
 
 
666
//Vec4ArrayShaderUniform
 
667
 
 
668
Vec4ArrayShaderUniform::Vec4ArrayShaderUniform(Shader* shader, const std::string& name, size_t length, const vec4* value) :
 
669
    length(length), ShaderUniform(shader, name, SHADER_UNIFORM_VEC4_ARRAY, "vec4") {
 
670
    this->value = new vec4[length];
 
671
    if(value != 0) copyValue(value);
 
672
}
 
673
 
 
674
Vec4ArrayShaderUniform::~Vec4ArrayShaderUniform() {
 
675
    if(value) delete[] value;
 
676
}
 
677
 
 
678
const vec4* Vec4ArrayShaderUniform::getValue() const {
 
679
    return value;
 
680
}
 
681
 
 
682
void Vec4ArrayShaderUniform::copyValue(const std::vector<vec4>& value) {
 
683
    for(size_t i=0; i<length; i++) {
 
684
        this->value[i] = value[i];
 
685
    }
 
686
}
 
687
 
 
688
void Vec4ArrayShaderUniform::copyValue(const vec4* value) {
 
689
    for(size_t i=0; i<length; i++) {
 
690
        this->value[i] = value[i];
 
691
    }
 
692
}
 
693
 
 
694
void Vec4ArrayShaderUniform::setValue(const vec4* value) {
 
695
    if(baked) {
 
696
        bool match = true;
 
697
 
 
698
        for(size_t i=0;i<length;i++) {
 
699
            if(value[i] != this->value[i]) {
 
700
                match = false;
 
701
                break;
 
702
            }
 
703
        }
 
704
 
 
705
        if(match) return;
 
706
    }
 
707
 
 
708
    copyValue(value);
 
709
 
 
710
    modified = true;
 
711
    initialized = true;
 
712
}
 
713
 
 
714
void Vec4ArrayShaderUniform::setValue(const std::vector<vec4>& value) {
 
715
    if(baked) {
 
716
        bool match = true;
 
717
 
 
718
        for(size_t i=0;i<length;i++) {
 
719
            if(value[i] != this->value[i]) {
 
720
                match = false;
 
721
                break;
 
722
            }
 
723
        }
 
724
 
 
725
        if(match) return;
 
726
    }
 
727
 
 
728
    copyValue(value);
 
729
 
 
730
    modified = true;
 
731
    initialized = true;
 
732
}
 
733
 
 
734
void Vec4ArrayShaderUniform::apply() {
 
735
    glUniform4fv(getLocation(), length, glm::value_ptr(value[0]));
 
736
}
 
737
 
 
738
void Vec4ArrayShaderUniform::write(std::string& content) const {
 
739
 
 
740
    char buff[1024];
 
741
 
 
742
    if(baked) {
 
743
        snprintf(buff, 1024, "%s[%ld] %s = %s[] (\n", type_name.c_str(), length, name.c_str(), type_name.c_str());
 
744
 
 
745
        content += buff;
 
746
 
 
747
        for(size_t i=0; i<length; i++) {
 
748
            snprintf(buff, 1024, "    %s(%e, %e, %e, %e)", type_name.c_str(), value[i].x, value[i].y, value[i].z, value[i].w);
 
749
            content += buff;
 
750
            if(i<length-1) content += ",\n";
 
751
            else           content += "\n);\n";
 
752
        }
 
753
 
 
754
    } else {
 
755
        snprintf(buff, 1024, "uniform %s %s[%ld];\n", type_name.c_str(), name.c_str(), length);
 
756
        content += buff;
 
757
    }
 
758
 
 
759
}
 
760
 
 
761
//ShaderPass
 
762
 
 
763
ShaderPass::ShaderPass(Shader* parent, GLint shader_object_type, const std::string& shader_object_desc) : parent(parent), shader_object_type(shader_object_type), shader_object_desc(shader_object_desc) {
 
764
    shader_object = 0;
 
765
    version = 0;
 
766
}
 
767
 
 
768
ShaderPass::~ShaderPass() {
 
769
    unload();
 
770
}
 
771
 
 
772
void ShaderPass::unload() {
 
773
    if(shader_object!=0) glDeleteShader(shader_object);
 
774
    shader_object = 0;
 
775
}
 
776
 
 
777
void ShaderPass::attachTo(GLenum program) {
 
778
    glAttachShader(program, shader_object);
 
779
}
 
780
 
 
781
bool ShaderPass::errorContext(const char* log_message, std::string& context) {
 
782
 
 
783
    std::vector<std::string> matches;
 
784
 
 
785
    if(   !Shader_error_line.match(log_message, &matches)
 
786
       && !Shader_error2_line.match(log_message, &matches)
 
787
       && !(shadermanager.warnings && Shader_warning_line.match(log_message, &matches)))
 
788
        return false;
 
789
 
 
790
    int line_no = atoi(matches[0].c_str());
 
791
 
 
792
    std::stringstream in(shader_object_source);
 
793
 
 
794
    int i = 1;
 
795
    int amount = 3;
 
796
 
 
797
    char line_detail[1024];
 
798
 
 
799
    std::string line;
 
800
    while( std::getline(in,line) ) {
 
801
 
 
802
        if(i==line_no || i<line_no && i+amount>=line_no || i>line_no && i-amount<=line_no) {
 
803
            snprintf(line_detail, 1024, "%s%4d | %s\n", (i==line_no ? "-> ": "   "), i, line.c_str());
 
804
            context += line_detail;
 
805
        }
 
806
        i++;
 
807
    }
 
808
 
 
809
    return true;
 
810
}
 
811
 
 
812
void ShaderPass::checkError() {
 
813
    if(!shader_object) return;
 
814
 
 
815
    GLint compile_success;
 
816
    glGetShaderiv(shader_object, GL_COMPILE_STATUS, &compile_success);
80
817
 
81
818
    GLint info_log_length;
82
 
    glGetShaderiv(shaderRef, GL_INFO_LOG_LENGTH, &info_log_length);
 
819
    glGetShaderiv(shader_object, GL_INFO_LOG_LENGTH, &info_log_length);
 
820
 
 
821
    const char* resource_desc = !parent->resource_name.empty() ? parent->resource_name.c_str() : "???";
83
822
 
84
823
    if(info_log_length > 1) {
85
824
        char info_log[info_log_length];
86
825
 
87
 
        glGetShaderInfoLog(shaderRef, info_log_length, &info_log_length, info_log);
 
826
        glGetShaderInfoLog(shader_object, info_log_length, &info_log_length, info_log);
 
827
 
 
828
        std::string context;
 
829
        errorContext(info_log, context);
88
830
 
89
831
        if(!compile_success) {
90
 
            throw SDLAppException("shader '%s' failed to compile: %s", filename.c_str(), info_log);
 
832
            throw SDLAppException("%s shader '%s' failed to compile:\n%s\n%s",
 
833
                                  shader_object_desc.c_str(),
 
834
                                  resource_desc,
 
835
                                  info_log,
 
836
                                  context.c_str());
 
837
 
 
838
 
 
839
 
91
840
        }
92
 
        
93
 
        if(shadermanager.debug) {
94
 
            fprintf(stderr, "%s: %s\n", filename.c_str(), info_log);
 
841
 
 
842
        if(shadermanager.warnings) {
 
843
            warnLog("%s shader '%s':\n%s\n%s",
 
844
                            shader_object_desc.c_str(),
 
845
                            resource_desc,
 
846
                            info_log,
 
847
                            context.c_str());
 
848
 
95
849
        }
96
850
 
97
851
        return;
98
852
    }
99
 
    
 
853
 
100
854
    if(!compile_success) {
101
 
        throw SDLAppException("shader '%s' failed to compile", filename.c_str());
102
 
    }
103
 
}
104
 
 
105
 
GLenum Shader::load(const std::string& filename, GLenum shaderType) {
106
 
 
107
 
    std::string source;
108
 
    readSource(filename, source);
109
 
 
110
 
    if(source.empty()) {
111
 
        throw SDLAppException("could not read shader '%s'", filename.c_str());
112
 
    }
113
 
 
114
 
    GLenum shaderRef = glCreateShader(shaderType);
115
 
 
116
 
    const char* source_ptr = source.c_str();
117
 
    int source_len = source.size();
118
 
 
119
 
    glShaderSource(shaderRef, 1, (const GLchar**) &source_ptr, &source_len);
120
 
 
121
 
    glCompileShader(shaderRef);
122
 
    
123
 
    checkError(filename, shaderRef);
124
 
 
125
 
    return shaderRef;
126
 
}
127
 
 
128
 
 
129
 
bool Shader::preprocess(const std::string& line, std::string& output) {
 
855
        throw SDLAppException("%s shader '%s' failed to compile",
 
856
                              shader_object_desc.c_str(),
 
857
                              resource_desc);
 
858
    }
 
859
}
 
860
 
 
861
void ShaderPass::toString(std::string& out) {
 
862
    if(version!=0) {
 
863
        out.append(str(boost::format("#version %d\n") % version));
 
864
    }
 
865
 
 
866
    for(std::map<std::string, std::string>::iterator it = extensions.begin(); it != extensions.end(); it++) {
 
867
        out.append(str(boost::format("#extension %s : %s\n") % it->first % it->second));
 
868
    }
 
869
 
 
870
    foreach(ShaderUniform* u, uniforms) {
 
871
        u->write(out);
 
872
    }
 
873
 
 
874
    out.append(source);
 
875
}
 
876
 
 
877
void ShaderPass::compile() {
 
878
 
 
879
    if(!shader_object) shader_object = glCreateShader(shader_object_type);
 
880
 
 
881
    if(source.empty()) return;
 
882
 
 
883
    shader_object_source.clear();
 
884
 
 
885
    toString(shader_object_source);
 
886
 
 
887
    // apply subsitutions
 
888
    parent->applySubstitutions(shader_object_source);
 
889
 
 
890
    foreach(ShaderUniform* u, uniforms) {
 
891
        u->setModified(false);
 
892
    }
 
893
 
 
894
    //fprintf(stderr, "src:\n%s", shader_object_source.c_str());
 
895
 
 
896
    const char* source_ptr = shader_object_source.c_str();
 
897
    int source_len = shader_object_source.size();
 
898
 
 
899
    glShaderSource(shader_object, 1, (const GLchar**) &source_ptr, &source_len);
 
900
    glCompileShader(shader_object);
 
901
 
 
902
    checkError();
 
903
}
 
904
 
 
905
//add uniform, unless parent Shader has this in which case link to it
 
906
ShaderUniform* ShaderPass::addArrayUniform(const std::string& name, const std::string& type, size_t length) {
 
907
 
 
908
    ShaderUniform* uniform = 0;
 
909
 
 
910
    if((uniform = parent->getUniform(name)) == 0) {
 
911
 
 
912
        if(type == "vec2") {
 
913
            uniform = new Vec2ArrayShaderUniform(parent, name, length);
 
914
        } else if(type == "vec3") {
 
915
            uniform = new Vec3ArrayShaderUniform(parent, name, length);
 
916
        } else if(type == "vec4") {
 
917
            uniform = new Vec4ArrayShaderUniform(parent, name, length);
 
918
        } else {
 
919
            throw SDLAppException("shader uniform arrays for type '%s' not implemented", type.c_str());
 
920
        }
 
921
 
 
922
        uniform->setInitialized(false);
 
923
 
 
924
        parent->addUniform(uniform);
 
925
    }
 
926
 
 
927
    uniforms.push_back(uniform);
 
928
 
 
929
    return uniform;
 
930
}
 
931
 
 
932
ShaderUniform* ShaderPass::addUniform(const std::string& name, const std::string& type) {
 
933
 
 
934
    ShaderUniform* uniform = 0;
 
935
 
 
936
    if((uniform = parent->getUniform(name)) == 0) {
 
937
 
 
938
        if(type == "float") {
 
939
            uniform = new FloatShaderUniform(parent, name);
 
940
        } else if(type == "int") {
 
941
            uniform = new IntShaderUniform(parent, name);
 
942
        } else if(type == "bool") {
 
943
            uniform = new BoolShaderUniform(parent, name);
 
944
        } else if(type == "sampler1D") {
 
945
            uniform = new Sampler1DShaderUniform(parent, name);
 
946
        } else if(type == "sampler2D") {
 
947
            uniform = new Sampler2DShaderUniform(parent, name);
 
948
        } else if(type == "vec2") {
 
949
            uniform = new Vec2ShaderUniform(parent, name);
 
950
        } else if(type == "vec3") {
 
951
            uniform = new Vec3ShaderUniform(parent, name);
 
952
        } else if(type == "vec4") {
 
953
            uniform = new Vec4ShaderUniform(parent, name);
 
954
        } else if(type == "mat3") {
 
955
            uniform = new Mat3ShaderUniform(parent, name);
 
956
        } else if(type == "mat4") {
 
957
            uniform = new Mat4ShaderUniform(parent, name);
 
958
        } else {
 
959
            throw SDLAppException("unsupported shader uniform type '%s'", type.c_str());
 
960
        }
 
961
 
 
962
        uniform->setInitialized(false);
 
963
 
 
964
        parent->addUniform(uniform);
 
965
    }
 
966
 
 
967
    uniforms.push_back(uniform);
 
968
 
 
969
    return uniform;
 
970
}
 
971
 
 
972
bool ShaderPass::preprocess(const std::string& line) {
130
973
 
131
974
    std::vector<std::string> matches;
132
975
 
 
976
    if(Shader_pre_version.match(line, &matches)) {
 
977
        version = atoi(matches[0].c_str());
 
978
        return true;
 
979
    }
 
980
 
 
981
    if(Shader_pre_extension.match(line, &matches)) {
 
982
        extensions[matches[0]] = matches[1];
 
983
        return true;
 
984
    }
 
985
 
133
986
    if(Shader_pre_include.match(line, &matches)) {
134
987
 
135
988
        std::string include_file = shadermanager.getDir() + matches[0];
136
989
 
137
 
        readSource(include_file, output);
 
990
        includeFile(include_file);
 
991
 
 
992
        return true;
 
993
    }
 
994
 
 
995
    if(Shader_uniform_def.match(line, &matches)) {
 
996
        std::string uniform_type = matches[0];
 
997
        std::string uniform_name = matches[1];
 
998
 
 
999
        if(matches.size() > 2) {
 
1000
            size_t uniform_length = atoi(matches[2].c_str());
 
1001
            addArrayUniform(uniform_name, uniform_type, uniform_length);
 
1002
        } else {
 
1003
            addUniform(uniform_name, uniform_type);
 
1004
        }
138
1005
 
139
1006
        return true;
140
1007
    }
141
1008
 
142
1009
    return false;
143
 
 
144
1010
}
145
1011
 
146
 
bool Shader::readSource(const std::string& file, std::string& output) {
 
1012
void ShaderPass::includeFile(const std::string& filename) {
147
1013
 
148
1014
    // get length
149
 
    std::ifstream in(file.c_str());
 
1015
    std::ifstream in(filename.c_str());
150
1016
 
151
1017
    if(!in.is_open()) {
152
 
        throw SDLAppException("could not open '%s'", file.c_str());
 
1018
        throw SDLAppException("could not open '%s'", filename.c_str());
153
1019
    }
154
1020
 
155
1021
    std::string line;
156
1022
    while( std::getline(in,line) ) {
157
 
        if(!preprocess(line, output)) {            
158
 
            output += line;
159
 
            output += "\n";
 
1023
        if(!preprocess(line)) {
 
1024
            source += line;
 
1025
            source += "\n";
160
1026
        }
161
1027
    }
162
1028
 
163
1029
    in.close();
164
 
    
165
 
    return true;
 
1030
}
 
1031
 
 
1032
void ShaderPass::includeSource(const std::string& string) {
 
1033
 
 
1034
    std::stringstream in(string);
 
1035
 
 
1036
    std::string line;
 
1037
    while( std::getline(in,line) ) {
 
1038
        if(!preprocess(line)) {
 
1039
            source += line;
 
1040
            source += "\n";
 
1041
        }
 
1042
    }
 
1043
}
 
1044
 
 
1045
VertexShader::VertexShader(Shader* parent) : ShaderPass(parent, GL_VERTEX_SHADER, "vertex") {
 
1046
}
 
1047
 
 
1048
FragmentShader::FragmentShader(Shader* parent) : ShaderPass(parent, GL_FRAGMENT_SHADER, "fragment") {
 
1049
}
 
1050
 
 
1051
GeometryShader::GeometryShader(Shader* parent) : ShaderPass(parent, GL_GEOMETRY_SHADER_ARB, "geometry") {
 
1052
}
 
1053
 
 
1054
void GeometryShader::attachTo(GLenum program) {
 
1055
    ShaderPass::attachTo(program);
 
1056
}
 
1057
 
 
1058
//Shader
 
1059
 
 
1060
Shader::Shader(const std::string& prefix) : Resource(prefix) {
 
1061
 
 
1062
    setDefaults();
 
1063
 
 
1064
    std::string shader_dir = shadermanager.getDir();
 
1065
 
 
1066
    std::string vertex_file   = shader_dir + prefix + std::string(".vert");
 
1067
    std::string fragment_file = shader_dir + prefix + std::string(".frag");
 
1068
 
 
1069
    vertex_shader = new VertexShader(this);
 
1070
    vertex_shader->includeFile(vertex_file);
 
1071
 
 
1072
    fragment_shader = new FragmentShader(this);
 
1073
    fragment_shader->includeFile(fragment_file);
 
1074
 
 
1075
    load();
 
1076
}
 
1077
 
 
1078
Shader::Shader() {
 
1079
    setDefaults();
 
1080
}
 
1081
 
 
1082
void Shader::setDynamicCompile(bool dynamic_compile) {
 
1083
    this->dynamic_compile = dynamic_compile;
 
1084
}
 
1085
 
 
1086
void Shader::setDefaults() {
 
1087
    vertex_shader   = 0;
 
1088
    fragment_shader = 0;
 
1089
    geometry_shader = 0;
 
1090
    program = 0;
 
1091
    dynamic_compile = false;
 
1092
}
 
1093
 
 
1094
Shader::~Shader() {
 
1095
    clear();
 
1096
}
 
1097
 
 
1098
void Shader::clear() {
 
1099
    unload();
 
1100
 
 
1101
    for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) {
 
1102
        delete it->second;
 
1103
    }
 
1104
    uniforms.clear();
 
1105
 
 
1106
    if(vertex_shader != 0)   delete vertex_shader;
 
1107
    if(geometry_shader != 0) delete geometry_shader;
 
1108
    if(fragment_shader != 0) delete fragment_shader;
 
1109
 
 
1110
    vertex_shader   = 0;
 
1111
    geometry_shader = 0;
 
1112
    fragment_shader = 0;
 
1113
}
 
1114
 
 
1115
void Shader::unload() {
 
1116
    if(program != 0) glDeleteProgram(program);
 
1117
    program = 0;
 
1118
 
 
1119
    for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) {
 
1120
        it->second->unload();
 
1121
    }
 
1122
}
 
1123
 
 
1124
void Shader::load() {
 
1125
    //fprintf(stderr, "load\n");
 
1126
 
 
1127
    if(program !=0) unload();
 
1128
 
 
1129
    if(vertex_shader != 0)   vertex_shader->compile();
 
1130
    if(geometry_shader != 0) geometry_shader->compile();
 
1131
    if(fragment_shader != 0) fragment_shader->compile();
 
1132
 
 
1133
    program = glCreateProgram();
 
1134
 
 
1135
    if(vertex_shader!=0)   vertex_shader->attachTo(program);
 
1136
    if(geometry_shader!=0) geometry_shader->attachTo(program);
 
1137
    if(fragment_shader!=0) fragment_shader->attachTo(program);
 
1138
 
 
1139
    glLinkProgram(program);
 
1140
 
 
1141
    checkProgramError();
 
1142
 
 
1143
    if(vertex_shader  != 0)  vertex_shader->unload();
 
1144
    if(geometry_shader != 0) geometry_shader->unload();
 
1145
    if(fragment_shader != 0) fragment_shader->unload();
 
1146
}
 
1147
 
 
1148
void Shader::checkProgramError() {
 
1149
 
 
1150
    GLint link_success;
 
1151
    glGetProgramiv(program, GL_LINK_STATUS, &link_success);
 
1152
 
 
1153
    GLint info_log_length;
 
1154
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);
 
1155
 
 
1156
    const char* resource_desc = !resource_name.empty() ? resource_name.c_str() : "???";
 
1157
 
 
1158
    if(info_log_length > 1) {
 
1159
        char info_log[info_log_length];
 
1160
 
 
1161
        glGetProgramInfoLog(program, info_log_length, &info_log_length, info_log);
 
1162
 
 
1163
        if(!link_success) {
 
1164
            throw SDLAppException("shader '%s' failed to link:\n%s",
 
1165
                                  resource_desc,
 
1166
                                  info_log);
 
1167
        }
 
1168
 
 
1169
        if(shadermanager.warnings) {
 
1170
            warnLog("shader '%s':\n%s",
 
1171
                            resource_desc,
 
1172
                            info_log);
 
1173
        }
 
1174
 
 
1175
        return;
 
1176
    }
 
1177
 
 
1178
    if(!link_success) {
 
1179
        throw SDLAppException("shader '%s' failed to link",
 
1180
                              resource_desc);
 
1181
    }
 
1182
}
 
1183
 
 
1184
void Shader::bind() {
 
1185
    glUseProgram(program);
 
1186
}
 
1187
 
 
1188
void Shader::unbind() {
 
1189
    glUseProgram(0);
166
1190
}
167
1191
 
168
1192
void Shader::use() {
169
 
    glUseProgram(shaderProg);
 
1193
 
 
1194
    if(shadermanager.warnings) {
 
1195
        for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) {
 
1196
            ShaderUniform* u = it->second;
 
1197
 
 
1198
            if(!u->isInitialized()) warnLog("shader '%s': uniform '%s' was never initialized", (!resource_name.empty() ? resource_name.c_str() : "???"), u->getName().c_str());
 
1199
        }
 
1200
    }
 
1201
 
 
1202
    if(dynamic_compile && needsCompile()) {
 
1203
        unbind();
 
1204
        load();
 
1205
        infoLog("shader '%s' recompiled", resource_name.c_str());
 
1206
    }
 
1207
 
 
1208
    bind();
 
1209
 
 
1210
    applyUniforms();
170
1211
}
171
1212
 
172
1213
GLenum Shader::getProgram() {
173
 
    return shaderProg;
174
 
}
175
 
 
176
 
GLenum Shader::getVertexShader() {
177
 
    return vertexShader;
178
 
}
179
 
 
180
 
GLenum Shader::getFragmentShader() {
181
 
    return fragmentShader;
182
 
}
183
 
 
184
 
GLint Shader::getVarLocation(const std::string& name) {
185
 
 
186
 
    GLint loc = varMap[name] - 1;
187
 
 
188
 
    if(loc != -1) return loc;
189
 
 
190
 
    loc = glGetUniformLocation( shaderProg, name.c_str() );
191
 
 
192
 
    varMap[name] = loc + 1;
193
 
 
194
 
    return loc;
 
1214
    return program;
 
1215
}
 
1216
 
 
1217
void Shader::addUniform(ShaderUniform* uniform) {
 
1218
 
 
1219
    if(getUniform(uniform->getName()) != 0) {
 
1220
        throw SDLAppException("shader already has a uniform named '%s'", uniform->getName().c_str() );
 
1221
    }
 
1222
 
 
1223
    uniforms[uniform->getName()] = uniform;
 
1224
}
 
1225
 
 
1226
ShaderUniform* Shader::getUniform(const std::string& name) {
 
1227
    std::map<std::string, ShaderUniform*>::iterator it = uniforms.find(name);
 
1228
 
 
1229
    if(it != uniforms.end()) {
 
1230
        return it->second;
 
1231
    }
 
1232
    return 0;
 
1233
}
 
1234
 
 
1235
ShaderPass* Shader::grabShaderPass(GLenum shader_object_type) {
 
1236
 
 
1237
    ShaderPass* shader_pass = 0;
 
1238
 
 
1239
    switch(shader_object_type) {
 
1240
        case GL_VERTEX_SHADER:
 
1241
            if(!vertex_shader) vertex_shader = new VertexShader(this);
 
1242
            shader_pass = vertex_shader;
 
1243
            break;
 
1244
        case GL_GEOMETRY_SHADER_ARB:
 
1245
            if(!geometry_shader) geometry_shader = new GeometryShader(this);
 
1246
            shader_pass = geometry_shader;
 
1247
            break;
 
1248
        case GL_FRAGMENT_SHADER:
 
1249
            if(!fragment_shader) fragment_shader = new FragmentShader(this);
 
1250
            shader_pass = fragment_shader;
 
1251
            break;
 
1252
    }
 
1253
 
 
1254
    return shader_pass;
 
1255
}
 
1256
 
 
1257
 
 
1258
void Shader::includeSource(GLenum shader_object_type, const std::string& source) {
 
1259
 
 
1260
    ShaderPass* pass = grabShaderPass(shader_object_type);
 
1261
 
 
1262
    pass->includeSource(source);
 
1263
}
 
1264
 
 
1265
void Shader::includeFile(GLenum shader_object_type, const std::string& filename) {
 
1266
 
 
1267
    ShaderPass* pass = grabShaderPass(shader_object_type);
 
1268
 
 
1269
    pass->includeFile(filename);
 
1270
}
 
1271
 
 
1272
void Shader::addSubstitute(const std::string& name, const char *value, ...) {
 
1273
 
 
1274
    va_list vl;
 
1275
    char sub[4096];
 
1276
 
 
1277
    va_start(vl, value);
 
1278
        vsnprintf(sub, 4096, value, vl);
 
1279
    va_end(vl);
 
1280
 
 
1281
    substitutions[name] = sub;
 
1282
}
 
1283
 
 
1284
void Shader::substitute(std::string& source, const std::string& name, const std::string& value) {
 
1285
 
 
1286
    std::string::size_type next_match;
 
1287
 
 
1288
    for(next_match = source.find(name);
 
1289
        next_match != std::string::npos;
 
1290
        next_match = source.find(name, next_match)) {
 
1291
        source.replace(next_match, name.length(), value);
 
1292
        next_match += value.length();
 
1293
    }
 
1294
}
 
1295
 
 
1296
void Shader::applySubstitutions(std::string& source) {
 
1297
 
 
1298
    for(std::map<std::string, std::string>::iterator it = substitutions.begin(); it != substitutions.end(); it++) {
 
1299
        substitute(source, it->first, it->second);
 
1300
    }
 
1301
}
 
1302
 
 
1303
void Shader::setBool (const std::string& name, bool value) {
 
1304
    ShaderUniform* uniform = getUniform(name);
 
1305
 
 
1306
    if(!uniform || uniform->getType() != SHADER_UNIFORM_BOOL) return;
 
1307
 
 
1308
    ((BoolShaderUniform*)uniform)->setValue(value);
 
1309
}
 
1310
 
 
1311
void Shader::setInteger (const std::string& name, int value) {
 
1312
    ShaderUniform* uniform = getUniform(name);
 
1313
 
 
1314
    if(!uniform || uniform->getType() != SHADER_UNIFORM_INT) return;
 
1315
 
 
1316
    ((IntShaderUniform*)uniform)->setValue(value);
 
1317
}
 
1318
 
 
1319
void Shader::setSampler1D (const std::string& name, int value) {
 
1320
    ShaderUniform* uniform = getUniform(name);
 
1321
 
 
1322
    if(!uniform || uniform->getType() != SHADER_UNIFORM_SAMPLER_1D) return;
 
1323
 
 
1324
    ((Sampler1DShaderUniform*)uniform)->setValue(value);
 
1325
}
 
1326
 
 
1327
void Shader::setSampler2D (const std::string& name, int value) {
 
1328
    ShaderUniform* uniform = getUniform(name);
 
1329
 
 
1330
    if(!uniform || uniform->getType() != SHADER_UNIFORM_SAMPLER_2D) return;
 
1331
 
 
1332
    ((Sampler2DShaderUniform*)uniform)->setValue(value);
195
1333
}
196
1334
 
197
1335
void Shader::setFloat(const std::string& name, float value) {
198
 
    GLint loc = getVarLocation(name);
199
 
    glUniform1f(loc, value);
200
 
}
201
 
 
202
 
void Shader::setVec2 (const std::string& name, const vec2f& value) {
203
 
    GLint loc = getVarLocation(name);
204
 
    glUniform2fv(loc, 1, value);
205
 
}
206
 
 
207
 
void Shader::setVec3 (const std::string& name, const vec3f& value) {
208
 
    GLint loc = getVarLocation(name);
209
 
    glUniform3fv(loc, 1, value);
210
 
}
211
 
 
212
 
void Shader::setVec4 (const std::string& name, const vec4f& value) {
213
 
    GLint loc =  getVarLocation(name);
214
 
    glUniform4fv(loc, 1, value);
215
 
}
216
 
 
217
 
void Shader::setInteger (const std::string& name, int value) {
218
 
    GLint loc =  getVarLocation(name);
219
 
    glUniform1i(loc, value);
220
 
}
221
 
 
222
 
 
223
 
 
 
1336
    ShaderUniform* uniform = getUniform(name);
 
1337
 
 
1338
    if(!uniform || uniform->getType() != SHADER_UNIFORM_FLOAT) return;
 
1339
 
 
1340
    ((FloatShaderUniform*)uniform)->setValue(value);
 
1341
}
 
1342
 
 
1343
void Shader::setVec2 (const std::string& name, const vec2& value) {
 
1344
    ShaderUniform* uniform = getUniform(name);
 
1345
 
 
1346
    if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC2) return;
 
1347
 
 
1348
    ((Vec2ShaderUniform*)uniform)->setValue(value);
 
1349
}
 
1350
 
 
1351
void Shader::setVec3 (const std::string& name, const vec3& value) {
 
1352
    ShaderUniform* uniform = getUniform(name);
 
1353
 
 
1354
    if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC3) return;
 
1355
 
 
1356
    ((Vec3ShaderUniform*)uniform)->setValue(value);
 
1357
}
 
1358
 
 
1359
void Shader::setVec2Array (const std::string& name, vec2* value) {
 
1360
    ShaderUniform* uniform = getUniform(name);
 
1361
 
 
1362
    if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC2_ARRAY) return;
 
1363
 
 
1364
    ((Vec2ArrayShaderUniform*)uniform)->setValue(value);
 
1365
}
 
1366
 
 
1367
void Shader::setVec2Array (const std::string& name, std::vector<vec2>& value) {
 
1368
    ShaderUniform* uniform = getUniform(name);
 
1369
 
 
1370
    if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC2_ARRAY) return;
 
1371
 
 
1372
    ((Vec2ArrayShaderUniform*)uniform)->setValue(value);
 
1373
}
 
1374
 
 
1375
void Shader::setVec3Array (const std::string& name, vec3* value) {
 
1376
    ShaderUniform* uniform = getUniform(name);
 
1377
 
 
1378
    if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC3_ARRAY) return;
 
1379
 
 
1380
    ((Vec3ArrayShaderUniform*)uniform)->setValue(value);
 
1381
}
 
1382
 
 
1383
void Shader::setVec3Array (const std::string& name, std::vector<vec3>& value) {
 
1384
    ShaderUniform* uniform = getUniform(name);
 
1385
 
 
1386
    if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC3_ARRAY) return;
 
1387
 
 
1388
    ((Vec3ArrayShaderUniform*)uniform)->setValue(value);
 
1389
}
 
1390
 
 
1391
void Shader::setVec4Array (const std::string& name, vec4* value) {
 
1392
    ShaderUniform* uniform = getUniform(name);
 
1393
 
 
1394
    if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC4_ARRAY) return;
 
1395
 
 
1396
    ((Vec4ArrayShaderUniform*)uniform)->setValue(value);
 
1397
}
 
1398
 
 
1399
void Shader::setVec4Array (const std::string& name, std::vector<vec4>& value) {
 
1400
    ShaderUniform* uniform = getUniform(name);
 
1401
 
 
1402
    if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC4_ARRAY) return;
 
1403
 
 
1404
    ((Vec4ArrayShaderUniform*)uniform)->setValue(value);
 
1405
}
 
1406
 
 
1407
void Shader::setVec4 (const std::string& name, const vec4& value) {
 
1408
    ShaderUniform* uniform = getUniform(name);
 
1409
 
 
1410
    if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC4) return;
 
1411
 
 
1412
    ((Vec4ShaderUniform*)uniform)->setValue(value);
 
1413
}
 
1414
 
 
1415
void Shader::setMat3 (const std::string& name, const mat3& value) {
 
1416
    ShaderUniform* uniform = getUniform(name);
 
1417
 
 
1418
    if(!uniform || uniform->getType() != SHADER_UNIFORM_MAT3) return;
 
1419
 
 
1420
    ((Mat3ShaderUniform*)uniform)->setValue(value);
 
1421
}
 
1422
 
 
1423
void Shader::setMat4 (const std::string& name, const mat4& value) {
 
1424
    ShaderUniform* uniform = getUniform(name);
 
1425
 
 
1426
    if(!uniform || uniform->getType() != SHADER_UNIFORM_MAT4) return;
 
1427
 
 
1428
    ((Mat4ShaderUniform*)uniform)->setValue(value);
 
1429
}
 
1430
 
 
1431
void Shader::setBaked(const std::string& name, bool baked) {
 
1432
    ShaderUniform* uniform = getUniform(name);
 
1433
 
 
1434
    if(!uniform) return;
 
1435
 
 
1436
    uniform->setBaked(baked);
 
1437
}
 
1438
 
 
1439
void Shader::setBakedUniforms(bool baked) {
 
1440
    for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) {
 
1441
        it->second->setBaked(baked);
 
1442
    }
 
1443
}
 
1444
 
 
1445
 
 
1446
void Shader::applyUniforms() {
 
1447
    for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) {
 
1448
        if(!it->second->isBaked()) it->second->apply();
 
1449
    }
 
1450
}
 
1451
 
 
1452
bool Shader::needsCompile() {
 
1453
 
 
1454
    for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) {
 
1455
        ShaderUniform* u = it->second;
 
1456
 
 
1457
        if(u->isBaked() && u->isModified()) {
 
1458
            //infoLog("baked uniform %s needs update", u->getName().c_str());
 
1459
            return true;
 
1460
        }
 
1461
    }
 
1462
 
 
1463
    return false;
 
1464
}