46
60
return (Shader*) s;
50
Shader::Shader(const std::string& prefix) : Resource(prefix) {
52
std::string shader_dir = shadermanager.getDir();
54
std::string vertexSrc = shader_dir + prefix + std::string(".vert");
55
std::string fragmentSrc = shader_dir + prefix + std::string(".frag");
57
vertexShader = load(vertexSrc, GL_VERTEX_SHADER);
58
fragmentShader = load(fragmentSrc, GL_FRAGMENT_SHADER);
64
glDeleteShader(vertexShader);
65
glDeleteShader(fragmentShader);
66
glDeleteProgram(shaderProg);
69
void Shader::makeProgram() {
70
shaderProg = glCreateProgram();
71
glAttachShader(shaderProg,fragmentShader);
72
glAttachShader(shaderProg,vertexShader);
73
glLinkProgram(shaderProg);
76
void Shader::checkError(const std::string& filename, GLenum shaderRef) {
78
GLint compile_success;
79
glGetShaderiv(shaderRef, GL_COMPILE_STATUS, &compile_success);
63
void ShaderManager::manage(Shader* shader) {
65
if(shader->resource_name.empty()) {
66
throw SDLAppException("Cannot manage shader with no resource name");
69
if(resources[shader->resource_name] != 0) {
70
throw SDLAppException("A shader resource already exists under the name '%s'", shader->resource_name.c_str());
73
resources[shader->resource_name] = shader;
78
void ShaderManager::unload() {
79
for(std::map<std::string, Resource*>::iterator it= resources.begin(); it!=resources.end();it++) {
80
((Shader*)it->second)->unload();
84
void ShaderManager::reload() {
85
for(std::map<std::string, Resource*>::iterator it= resources.begin(); it!=resources.end();it++) {
86
((Shader*)it->second)->load();
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) {
96
void ShaderUniform::unload() {
100
const std::string& ShaderUniform::getName() const {
104
GLint ShaderUniform::getLocation() {
106
// TODO: (re-)compiling the shader should break the uniform location caching.
108
if(location != -1) return location;
110
location = glGetUniformLocation( shader->getProgram(), name.c_str() );
115
void ShaderUniform::setBaked(bool baked) {
116
if(this->baked == baked) return;
124
FloatShaderUniform::FloatShaderUniform(Shader* shader, const std::string& name, float value) :
125
value(value), ShaderUniform(shader, name, SHADER_UNIFORM_FLOAT, "float") {
128
void FloatShaderUniform::setValue(float value) {
129
if(baked && this->value == value) return;
136
void FloatShaderUniform::apply() {
137
glUniform1f(getLocation(), value);
140
float FloatShaderUniform::getValue() const {
144
void FloatShaderUniform::write(std::string& content) const {
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);
152
snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
160
IntShaderUniform::IntShaderUniform(Shader* shader, const std::string& name, int value) :
161
value(value), ShaderUniform(shader, name, SHADER_UNIFORM_INT, "int") {
164
void IntShaderUniform::setValue(int value) {
165
if(baked && this->value == value) return;
172
void IntShaderUniform::apply() {
173
glUniform1i(getLocation(), value);
176
float IntShaderUniform::getValue() const {
180
void IntShaderUniform::write(std::string& content) const {
185
snprintf(buff, 256, "#define %s %d\n", name.c_str(), value);
187
snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
195
BoolShaderUniform::BoolShaderUniform(Shader* shader, const std::string& name, bool value) :
196
value(value), ShaderUniform(shader, name, SHADER_UNIFORM_BOOL, "bool") {
199
void BoolShaderUniform::setValue(bool value) {
200
if(baked && this->value == value) return;
207
void BoolShaderUniform::apply() {
208
glUniform1i(getLocation(), value);
211
float BoolShaderUniform::getValue() const {
215
void BoolShaderUniform::write(std::string& content) const {
220
snprintf(buff, 256, "#define %s %s\n", name.c_str(), value ? "true" : "false");
222
snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
228
//Sampler1DShaderUniform
230
Sampler1DShaderUniform::Sampler1DShaderUniform(Shader* shader, const std::string& name, int value) :
231
value(value), ShaderUniform(shader, name, SHADER_UNIFORM_SAMPLER_1D, "sampler1D") {
234
void Sampler1DShaderUniform::setValue(int value) {
235
if(baked && this->value == value) return;
242
void Sampler1DShaderUniform::setBaked(bool baked) {
245
void Sampler1DShaderUniform::write(std::string& content) const {
247
snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
251
void Sampler1DShaderUniform::apply() {
252
glUniform1i(getLocation(), value);
255
float Sampler1DShaderUniform::getValue() const {
259
//Sampler2DShaderUniform
261
Sampler2DShaderUniform::Sampler2DShaderUniform(Shader* shader, const std::string& name, int value) :
262
value(value), ShaderUniform(shader, name, SHADER_UNIFORM_SAMPLER_2D, "sampler2D") {
265
void Sampler2DShaderUniform::setValue(int value) {
266
if(baked && this->value == value) return;
273
void Sampler2DShaderUniform::apply() {
274
glUniform1i(getLocation(), value);
277
float Sampler2DShaderUniform::getValue() const {
282
void Sampler2DShaderUniform::setBaked(bool baked) {
285
void Sampler2DShaderUniform::write(std::string& content) const {
287
snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
294
Vec2ShaderUniform::Vec2ShaderUniform(Shader* shader, const std::string& name, const vec2& value) :
295
value(value), ShaderUniform(shader, name, SHADER_UNIFORM_VEC2, "vec2") {
298
void Vec2ShaderUniform::setValue(const vec2& value) {
299
if(baked && this->value == value) return;
306
void Vec2ShaderUniform::apply() {
307
glUniform2fv(getLocation(), 1, glm::value_ptr(value));
310
const vec2& Vec2ShaderUniform::getValue() const {
314
void Vec2ShaderUniform::write(std::string& content) const {
319
snprintf(buff, 256, "#define %s vec2(%e, %e)\n", name.c_str(), value.x, value.y);
321
snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
329
Vec3ShaderUniform::Vec3ShaderUniform(Shader* shader, const std::string& name, const vec3& value) :
330
value(value), ShaderUniform(shader, name, SHADER_UNIFORM_VEC3, "vec3") {
334
void Vec3ShaderUniform::setValue(const vec3& value) {
335
if(baked && this->value == value) return;
342
void Vec3ShaderUniform::apply() {
343
glUniform3fv(getLocation(), 1, glm::value_ptr(value));
347
const vec3& Vec3ShaderUniform::getValue() const {
351
void Vec3ShaderUniform::write(std::string& content) const {
356
snprintf(buff, 256, "#define %s vec3(%e, %e, %e)\n", name.c_str(), value.x, value.y, value.z);
358
snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
366
Vec4ShaderUniform::Vec4ShaderUniform(Shader* shader, const std::string& name, const vec4& value) :
367
value(value), ShaderUniform(shader, name, SHADER_UNIFORM_VEC4, "vec4") {
370
void Vec4ShaderUniform::setValue(const vec4& value) {
371
if(baked && this->value == value) return;
378
void Vec4ShaderUniform::apply() {
379
glUniform4fv(getLocation(), 1, glm::value_ptr(value));
382
const vec4& Vec4ShaderUniform::getValue() const {
386
void Vec4ShaderUniform::write(std::string& content) const {
391
snprintf(buff, 256, "#define %s vec4(%e, %e, %e, %e)\n", name.c_str(), value.x, value.y, value.z, value.w);
393
snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str());
401
Mat3ShaderUniform::Mat3ShaderUniform(Shader* shader, const std::string& name, const mat3& value) :
402
value(value), ShaderUniform(shader, name, SHADER_UNIFORM_MAT3, "mat3") {
405
void Mat3ShaderUniform::setValue(const mat3& value) {
406
if(baked && this->value == value) return;
413
void Mat3ShaderUniform::apply() {
414
glUniformMatrix3fv(getLocation(), 1, 0, glm::value_ptr(value));
417
const mat3& Mat3ShaderUniform::getValue() const {
421
void Mat3ShaderUniform::write(std::string& content) const {
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]);
432
snprintf(buff, 1024, "uniform %s %s;\n", type_name.c_str(), name.c_str());
440
Mat4ShaderUniform::Mat4ShaderUniform(Shader* shader, const std::string& name, const mat4& value) :
441
value(value), ShaderUniform(shader, name, SHADER_UNIFORM_MAT4, "mat4") {
444
void Mat4ShaderUniform::setValue(const mat4& value) {
445
if(baked && this->value == value) return;
452
void Mat4ShaderUniform::apply() {
453
glUniformMatrix4fv(getLocation(), 1, 0, glm::value_ptr(value));
456
const mat4& Mat4ShaderUniform::getValue() const {
460
void Mat4ShaderUniform::write(std::string& content) const {
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]);
471
snprintf(buff, 1024, "uniform %s %s;\n", type_name.c_str(), name.c_str());
478
//Vec2ArrayShaderUniform
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);
486
Vec2ArrayShaderUniform::~Vec2ArrayShaderUniform() {
487
if(value) delete[] value;
490
const vec2* Vec2ArrayShaderUniform::getValue() const {
494
void Vec2ArrayShaderUniform::copyValue(const vec2* value) {
495
for(size_t i=0; i<length; i++) {
496
this->value[i] = value[i];
500
void Vec2ArrayShaderUniform::copyValue(const std::vector<vec2>& value) {
501
for(size_t i=0; i<length; i++) {
502
this->value[i] = value[i];
506
void Vec2ArrayShaderUniform::setValue(const vec2* value) {
510
for(size_t i=0;i<length;i++) {
511
if(value[i] != this->value[i]) {
526
void Vec2ArrayShaderUniform::setValue(const std::vector<vec2>& value) {
530
for(size_t i=0;i<length;i++) {
531
if(value[i] != this->value[i]) {
546
void Vec2ArrayShaderUniform::apply() {
547
glUniform2fv(getLocation(), length, glm::value_ptr(value[0]));
550
void Vec2ArrayShaderUniform::write(std::string& content) const {
555
snprintf(buff, 1024, "%s[%ld] %s = %s[] (\n", type_name.c_str(), length, name.c_str(), type_name.c_str());
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);
562
if(i<length-1) content += ",\n";
563
else content += "\n);\n";
567
snprintf(buff, 1024, "uniform %s %s[%ld];\n", type_name.c_str(), name.c_str(), length);
572
//Vec3ArrayShaderUniform
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);
580
Vec3ArrayShaderUniform::~Vec3ArrayShaderUniform() {
581
if(value) delete[] value;
584
const vec3* Vec3ArrayShaderUniform::getValue() const {
588
void Vec3ArrayShaderUniform::copyValue(const vec3* value) {
589
for(size_t i=0; i<length; i++) {
590
this->value[i] = value[i];
594
void Vec3ArrayShaderUniform::copyValue(const std::vector<vec3>& value) {
595
for(size_t i=0; i<length; i++) {
596
this->value[i] = value[i];
600
void Vec3ArrayShaderUniform::setValue(const vec3* value) {
604
for(size_t i=0;i<length;i++) {
605
if(value[i] != this->value[i]) {
620
void Vec3ArrayShaderUniform::setValue(const std::vector<vec3>& value) {
624
for(size_t i=0;i<length;i++) {
625
if(value[i] != this->value[i]) {
640
void Vec3ArrayShaderUniform::apply() {
641
glUniform3fv(getLocation(), length, glm::value_ptr(value[0]));
644
void Vec3ArrayShaderUniform::write(std::string& content) const {
649
snprintf(buff, 1024, "%s[%ld] %s = %s[] (\n", type_name.c_str(), length, name.c_str(), type_name.c_str());
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);
656
if(i<length-1) content += ",\n";
657
else content += "\n);\n";
661
snprintf(buff, 1024, "uniform %s %s[%ld];\n", type_name.c_str(), name.c_str(), length);
666
//Vec4ArrayShaderUniform
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);
674
Vec4ArrayShaderUniform::~Vec4ArrayShaderUniform() {
675
if(value) delete[] value;
678
const vec4* Vec4ArrayShaderUniform::getValue() const {
682
void Vec4ArrayShaderUniform::copyValue(const std::vector<vec4>& value) {
683
for(size_t i=0; i<length; i++) {
684
this->value[i] = value[i];
688
void Vec4ArrayShaderUniform::copyValue(const vec4* value) {
689
for(size_t i=0; i<length; i++) {
690
this->value[i] = value[i];
694
void Vec4ArrayShaderUniform::setValue(const vec4* value) {
698
for(size_t i=0;i<length;i++) {
699
if(value[i] != this->value[i]) {
714
void Vec4ArrayShaderUniform::setValue(const std::vector<vec4>& value) {
718
for(size_t i=0;i<length;i++) {
719
if(value[i] != this->value[i]) {
734
void Vec4ArrayShaderUniform::apply() {
735
glUniform4fv(getLocation(), length, glm::value_ptr(value[0]));
738
void Vec4ArrayShaderUniform::write(std::string& content) const {
743
snprintf(buff, 1024, "%s[%ld] %s = %s[] (\n", type_name.c_str(), length, name.c_str(), type_name.c_str());
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);
750
if(i<length-1) content += ",\n";
751
else content += "\n);\n";
755
snprintf(buff, 1024, "uniform %s %s[%ld];\n", type_name.c_str(), name.c_str(), length);
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) {
768
ShaderPass::~ShaderPass() {
772
void ShaderPass::unload() {
773
if(shader_object!=0) glDeleteShader(shader_object);
777
void ShaderPass::attachTo(GLenum program) {
778
glAttachShader(program, shader_object);
781
bool ShaderPass::errorContext(const char* log_message, std::string& context) {
783
std::vector<std::string> matches;
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)))
790
int line_no = atoi(matches[0].c_str());
792
std::stringstream in(shader_object_source);
797
char line_detail[1024];
800
while( std::getline(in,line) ) {
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;
812
void ShaderPass::checkError() {
813
if(!shader_object) return;
815
GLint compile_success;
816
glGetShaderiv(shader_object, GL_COMPILE_STATUS, &compile_success);
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);
821
const char* resource_desc = !parent->resource_name.empty() ? parent->resource_name.c_str() : "???";
84
823
if(info_log_length > 1) {
85
824
char info_log[info_log_length];
87
glGetShaderInfoLog(shaderRef, info_log_length, &info_log_length, info_log);
826
glGetShaderInfoLog(shader_object, info_log_length, &info_log_length, info_log);
829
errorContext(info_log, context);
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(),
93
if(shadermanager.debug) {
94
fprintf(stderr, "%s: %s\n", filename.c_str(), info_log);
842
if(shadermanager.warnings) {
843
warnLog("%s shader '%s':\n%s\n%s",
844
shader_object_desc.c_str(),
100
854
if(!compile_success) {
101
throw SDLAppException("shader '%s' failed to compile", filename.c_str());
105
GLenum Shader::load(const std::string& filename, GLenum shaderType) {
108
readSource(filename, source);
111
throw SDLAppException("could not read shader '%s'", filename.c_str());
114
GLenum shaderRef = glCreateShader(shaderType);
116
const char* source_ptr = source.c_str();
117
int source_len = source.size();
119
glShaderSource(shaderRef, 1, (const GLchar**) &source_ptr, &source_len);
121
glCompileShader(shaderRef);
123
checkError(filename, shaderRef);
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(),
861
void ShaderPass::toString(std::string& out) {
863
out.append(str(boost::format("#version %d\n") % version));
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));
870
foreach(ShaderUniform* u, uniforms) {
877
void ShaderPass::compile() {
879
if(!shader_object) shader_object = glCreateShader(shader_object_type);
881
if(source.empty()) return;
883
shader_object_source.clear();
885
toString(shader_object_source);
887
// apply subsitutions
888
parent->applySubstitutions(shader_object_source);
890
foreach(ShaderUniform* u, uniforms) {
891
u->setModified(false);
894
//fprintf(stderr, "src:\n%s", shader_object_source.c_str());
896
const char* source_ptr = shader_object_source.c_str();
897
int source_len = shader_object_source.size();
899
glShaderSource(shader_object, 1, (const GLchar**) &source_ptr, &source_len);
900
glCompileShader(shader_object);
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) {
908
ShaderUniform* uniform = 0;
910
if((uniform = parent->getUniform(name)) == 0) {
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);
919
throw SDLAppException("shader uniform arrays for type '%s' not implemented", type.c_str());
922
uniform->setInitialized(false);
924
parent->addUniform(uniform);
927
uniforms.push_back(uniform);
932
ShaderUniform* ShaderPass::addUniform(const std::string& name, const std::string& type) {
934
ShaderUniform* uniform = 0;
936
if((uniform = parent->getUniform(name)) == 0) {
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);
959
throw SDLAppException("unsupported shader uniform type '%s'", type.c_str());
962
uniform->setInitialized(false);
964
parent->addUniform(uniform);
967
uniforms.push_back(uniform);
972
bool ShaderPass::preprocess(const std::string& line) {
131
974
std::vector<std::string> matches;
976
if(Shader_pre_version.match(line, &matches)) {
977
version = atoi(matches[0].c_str());
981
if(Shader_pre_extension.match(line, &matches)) {
982
extensions[matches[0]] = matches[1];
133
986
if(Shader_pre_include.match(line, &matches)) {
135
988
std::string include_file = shadermanager.getDir() + matches[0];
137
readSource(include_file, output);
990
includeFile(include_file);
995
if(Shader_uniform_def.match(line, &matches)) {
996
std::string uniform_type = matches[0];
997
std::string uniform_name = matches[1];
999
if(matches.size() > 2) {
1000
size_t uniform_length = atoi(matches[2].c_str());
1001
addArrayUniform(uniform_name, uniform_type, uniform_length);
1003
addUniform(uniform_name, uniform_type);
146
bool Shader::readSource(const std::string& file, std::string& output) {
1012
void ShaderPass::includeFile(const std::string& filename) {
149
std::ifstream in(file.c_str());
1015
std::ifstream in(filename.c_str());
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());
155
1021
std::string line;
156
1022
while( std::getline(in,line) ) {
157
if(!preprocess(line, output)) {
1023
if(!preprocess(line)) {
1032
void ShaderPass::includeSource(const std::string& string) {
1034
std::stringstream in(string);
1037
while( std::getline(in,line) ) {
1038
if(!preprocess(line)) {
1045
VertexShader::VertexShader(Shader* parent) : ShaderPass(parent, GL_VERTEX_SHADER, "vertex") {
1048
FragmentShader::FragmentShader(Shader* parent) : ShaderPass(parent, GL_FRAGMENT_SHADER, "fragment") {
1051
GeometryShader::GeometryShader(Shader* parent) : ShaderPass(parent, GL_GEOMETRY_SHADER_ARB, "geometry") {
1054
void GeometryShader::attachTo(GLenum program) {
1055
ShaderPass::attachTo(program);
1060
Shader::Shader(const std::string& prefix) : Resource(prefix) {
1064
std::string shader_dir = shadermanager.getDir();
1066
std::string vertex_file = shader_dir + prefix + std::string(".vert");
1067
std::string fragment_file = shader_dir + prefix + std::string(".frag");
1069
vertex_shader = new VertexShader(this);
1070
vertex_shader->includeFile(vertex_file);
1072
fragment_shader = new FragmentShader(this);
1073
fragment_shader->includeFile(fragment_file);
1082
void Shader::setDynamicCompile(bool dynamic_compile) {
1083
this->dynamic_compile = dynamic_compile;
1086
void Shader::setDefaults() {
1088
fragment_shader = 0;
1089
geometry_shader = 0;
1091
dynamic_compile = false;
1098
void Shader::clear() {
1101
for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) {
1106
if(vertex_shader != 0) delete vertex_shader;
1107
if(geometry_shader != 0) delete geometry_shader;
1108
if(fragment_shader != 0) delete fragment_shader;
1111
geometry_shader = 0;
1112
fragment_shader = 0;
1115
void Shader::unload() {
1116
if(program != 0) glDeleteProgram(program);
1119
for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) {
1120
it->second->unload();
1124
void Shader::load() {
1125
//fprintf(stderr, "load\n");
1127
if(program !=0) unload();
1129
if(vertex_shader != 0) vertex_shader->compile();
1130
if(geometry_shader != 0) geometry_shader->compile();
1131
if(fragment_shader != 0) fragment_shader->compile();
1133
program = glCreateProgram();
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);
1139
glLinkProgram(program);
1141
checkProgramError();
1143
if(vertex_shader != 0) vertex_shader->unload();
1144
if(geometry_shader != 0) geometry_shader->unload();
1145
if(fragment_shader != 0) fragment_shader->unload();
1148
void Shader::checkProgramError() {
1151
glGetProgramiv(program, GL_LINK_STATUS, &link_success);
1153
GLint info_log_length;
1154
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);
1156
const char* resource_desc = !resource_name.empty() ? resource_name.c_str() : "???";
1158
if(info_log_length > 1) {
1159
char info_log[info_log_length];
1161
glGetProgramInfoLog(program, info_log_length, &info_log_length, info_log);
1164
throw SDLAppException("shader '%s' failed to link:\n%s",
1169
if(shadermanager.warnings) {
1170
warnLog("shader '%s':\n%s",
1179
throw SDLAppException("shader '%s' failed to link",
1184
void Shader::bind() {
1185
glUseProgram(program);
1188
void Shader::unbind() {
168
1192
void Shader::use() {
169
glUseProgram(shaderProg);
1194
if(shadermanager.warnings) {
1195
for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) {
1196
ShaderUniform* u = it->second;
1198
if(!u->isInitialized()) warnLog("shader '%s': uniform '%s' was never initialized", (!resource_name.empty() ? resource_name.c_str() : "???"), u->getName().c_str());
1202
if(dynamic_compile && needsCompile()) {
1205
infoLog("shader '%s' recompiled", resource_name.c_str());
172
1213
GLenum Shader::getProgram() {
176
GLenum Shader::getVertexShader() {
180
GLenum Shader::getFragmentShader() {
181
return fragmentShader;
184
GLint Shader::getVarLocation(const std::string& name) {
186
GLint loc = varMap[name] - 1;
188
if(loc != -1) return loc;
190
loc = glGetUniformLocation( shaderProg, name.c_str() );
192
varMap[name] = loc + 1;
1217
void Shader::addUniform(ShaderUniform* uniform) {
1219
if(getUniform(uniform->getName()) != 0) {
1220
throw SDLAppException("shader already has a uniform named '%s'", uniform->getName().c_str() );
1223
uniforms[uniform->getName()] = uniform;
1226
ShaderUniform* Shader::getUniform(const std::string& name) {
1227
std::map<std::string, ShaderUniform*>::iterator it = uniforms.find(name);
1229
if(it != uniforms.end()) {
1235
ShaderPass* Shader::grabShaderPass(GLenum shader_object_type) {
1237
ShaderPass* shader_pass = 0;
1239
switch(shader_object_type) {
1240
case GL_VERTEX_SHADER:
1241
if(!vertex_shader) vertex_shader = new VertexShader(this);
1242
shader_pass = vertex_shader;
1244
case GL_GEOMETRY_SHADER_ARB:
1245
if(!geometry_shader) geometry_shader = new GeometryShader(this);
1246
shader_pass = geometry_shader;
1248
case GL_FRAGMENT_SHADER:
1249
if(!fragment_shader) fragment_shader = new FragmentShader(this);
1250
shader_pass = fragment_shader;
1258
void Shader::includeSource(GLenum shader_object_type, const std::string& source) {
1260
ShaderPass* pass = grabShaderPass(shader_object_type);
1262
pass->includeSource(source);
1265
void Shader::includeFile(GLenum shader_object_type, const std::string& filename) {
1267
ShaderPass* pass = grabShaderPass(shader_object_type);
1269
pass->includeFile(filename);
1272
void Shader::addSubstitute(const std::string& name, const char *value, ...) {
1277
va_start(vl, value);
1278
vsnprintf(sub, 4096, value, vl);
1281
substitutions[name] = sub;
1284
void Shader::substitute(std::string& source, const std::string& name, const std::string& value) {
1286
std::string::size_type next_match;
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();
1296
void Shader::applySubstitutions(std::string& source) {
1298
for(std::map<std::string, std::string>::iterator it = substitutions.begin(); it != substitutions.end(); it++) {
1299
substitute(source, it->first, it->second);
1303
void Shader::setBool (const std::string& name, bool value) {
1304
ShaderUniform* uniform = getUniform(name);
1306
if(!uniform || uniform->getType() != SHADER_UNIFORM_BOOL) return;
1308
((BoolShaderUniform*)uniform)->setValue(value);
1311
void Shader::setInteger (const std::string& name, int value) {
1312
ShaderUniform* uniform = getUniform(name);
1314
if(!uniform || uniform->getType() != SHADER_UNIFORM_INT) return;
1316
((IntShaderUniform*)uniform)->setValue(value);
1319
void Shader::setSampler1D (const std::string& name, int value) {
1320
ShaderUniform* uniform = getUniform(name);
1322
if(!uniform || uniform->getType() != SHADER_UNIFORM_SAMPLER_1D) return;
1324
((Sampler1DShaderUniform*)uniform)->setValue(value);
1327
void Shader::setSampler2D (const std::string& name, int value) {
1328
ShaderUniform* uniform = getUniform(name);
1330
if(!uniform || uniform->getType() != SHADER_UNIFORM_SAMPLER_2D) return;
1332
((Sampler2DShaderUniform*)uniform)->setValue(value);
197
1335
void Shader::setFloat(const std::string& name, float value) {
198
GLint loc = getVarLocation(name);
199
glUniform1f(loc, value);
202
void Shader::setVec2 (const std::string& name, const vec2f& value) {
203
GLint loc = getVarLocation(name);
204
glUniform2fv(loc, 1, value);
207
void Shader::setVec3 (const std::string& name, const vec3f& value) {
208
GLint loc = getVarLocation(name);
209
glUniform3fv(loc, 1, value);
212
void Shader::setVec4 (const std::string& name, const vec4f& value) {
213
GLint loc = getVarLocation(name);
214
glUniform4fv(loc, 1, value);
217
void Shader::setInteger (const std::string& name, int value) {
218
GLint loc = getVarLocation(name);
219
glUniform1i(loc, value);
1336
ShaderUniform* uniform = getUniform(name);
1338
if(!uniform || uniform->getType() != SHADER_UNIFORM_FLOAT) return;
1340
((FloatShaderUniform*)uniform)->setValue(value);
1343
void Shader::setVec2 (const std::string& name, const vec2& value) {
1344
ShaderUniform* uniform = getUniform(name);
1346
if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC2) return;
1348
((Vec2ShaderUniform*)uniform)->setValue(value);
1351
void Shader::setVec3 (const std::string& name, const vec3& value) {
1352
ShaderUniform* uniform = getUniform(name);
1354
if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC3) return;
1356
((Vec3ShaderUniform*)uniform)->setValue(value);
1359
void Shader::setVec2Array (const std::string& name, vec2* value) {
1360
ShaderUniform* uniform = getUniform(name);
1362
if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC2_ARRAY) return;
1364
((Vec2ArrayShaderUniform*)uniform)->setValue(value);
1367
void Shader::setVec2Array (const std::string& name, std::vector<vec2>& value) {
1368
ShaderUniform* uniform = getUniform(name);
1370
if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC2_ARRAY) return;
1372
((Vec2ArrayShaderUniform*)uniform)->setValue(value);
1375
void Shader::setVec3Array (const std::string& name, vec3* value) {
1376
ShaderUniform* uniform = getUniform(name);
1378
if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC3_ARRAY) return;
1380
((Vec3ArrayShaderUniform*)uniform)->setValue(value);
1383
void Shader::setVec3Array (const std::string& name, std::vector<vec3>& value) {
1384
ShaderUniform* uniform = getUniform(name);
1386
if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC3_ARRAY) return;
1388
((Vec3ArrayShaderUniform*)uniform)->setValue(value);
1391
void Shader::setVec4Array (const std::string& name, vec4* value) {
1392
ShaderUniform* uniform = getUniform(name);
1394
if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC4_ARRAY) return;
1396
((Vec4ArrayShaderUniform*)uniform)->setValue(value);
1399
void Shader::setVec4Array (const std::string& name, std::vector<vec4>& value) {
1400
ShaderUniform* uniform = getUniform(name);
1402
if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC4_ARRAY) return;
1404
((Vec4ArrayShaderUniform*)uniform)->setValue(value);
1407
void Shader::setVec4 (const std::string& name, const vec4& value) {
1408
ShaderUniform* uniform = getUniform(name);
1410
if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC4) return;
1412
((Vec4ShaderUniform*)uniform)->setValue(value);
1415
void Shader::setMat3 (const std::string& name, const mat3& value) {
1416
ShaderUniform* uniform = getUniform(name);
1418
if(!uniform || uniform->getType() != SHADER_UNIFORM_MAT3) return;
1420
((Mat3ShaderUniform*)uniform)->setValue(value);
1423
void Shader::setMat4 (const std::string& name, const mat4& value) {
1424
ShaderUniform* uniform = getUniform(name);
1426
if(!uniform || uniform->getType() != SHADER_UNIFORM_MAT4) return;
1428
((Mat4ShaderUniform*)uniform)->setValue(value);
1431
void Shader::setBaked(const std::string& name, bool baked) {
1432
ShaderUniform* uniform = getUniform(name);
1434
if(!uniform) return;
1436
uniform->setBaked(baked);
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);
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();
1452
bool Shader::needsCompile() {
1454
for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) {
1455
ShaderUniform* u = it->second;
1457
if(u->isBaked() && u->isModified()) {
1458
//infoLog("baked uniform %s needs update", u->getName().c_str());