00001
00005 #include "material.h"
00006
00013 string LoadShader(const char* source)
00014 {
00015 ifstream fin(source);
00016 if(!fin)
00017 {
00018 string msg = "Cannot open shader ";
00019 msg += source;
00020 ShowMessage(msg.c_str(), false);
00021 return "null";
00022 }
00023 string data;
00024 char ch;
00025 while(fin.get(ch))
00026 data+=ch;
00027
00028 return data;
00029 }
00030
00032
00034
00035
00048 TMaterial::TMaterial(const char* _name, TVector amb, TVector diff, TVector spec, GLfloat shin, GLfloat reflect, GLfloat transp, GLint lm)
00049 {
00050 name = _name;
00051 ambColor = amb;
00052 diffColor = diff;
00053 specColor = spec;
00054 shininess = shin;
00055 reflection = reflect;
00056 transparency = transp;
00057 lightModel = lm;
00058
00059 shader = gshader_ref = 0;
00060 baked = false;
00061 useMRT = false;
00062 custom_shader = false;
00063 receive_shadows = true;
00064 use_gshader_ref = false;
00065 }
00066
00071 TMaterial::~TMaterial()
00072 {
00073 if(shader != 0)
00074 {
00075 glDetachObjectARB(shader,f_shader);
00076 glDetachObjectARB(shader,g_shader);
00077 glDetachObjectARB(shader,v_shader);
00078 glDeleteObjectARB(shader);
00079 }
00080 }
00081
00082
00090 string TMaterial::NextTexture(string texname)
00091 {
00092 int i = 1;
00093 for(it = textures.begin(); it != textures.end(); it++)
00094 {
00096 if(texname == it->first || it->first.empty() )
00097 {
00098 string rep;
00099 rep = num2str(char('A' + i));
00100 texname.replace(texname.length()-1, rep.size(), rep.c_str());
00101 i++;
00102 }
00103 }
00104 return texname;
00105 }
00106
00121 GLint TMaterial::AddTexture(const char *file, GLint textype, GLint texmode, GLfloat intensity, GLfloat tileX, GLfloat tileY, bool mipmap, bool aniso, GLint cache)
00122 {
00124 string texname;
00125 switch(textype)
00126 {
00127
00128 case BASE: texname = NextTexture(name + "BaseA"); break;
00129
00130 case ALPHA: texname = NextTexture(name + "AlphaA"); break;
00131
00132 case ENV: texname = NextTexture(name + "EnvA"); break;
00133
00134 case BUMP: texname = NextTexture(name + "BumpA"); break;
00135
00136 case PARALLAX: texname = NextTexture(name + "ParallaxA"); break;
00137
00138 case DISPLACE: texname = NextTexture(name + "DisplaceA"); break;
00139
00140 case CUBEMAP: texname = NextTexture(name + "CubeA"); break;
00141
00142 case CUBEMAP_ENV: texname = name + "CubeEnvA"; break;
00143
00144 case RENDER_TEXTURE: texname = "renderTexture"; break;
00145 case BLOOM_TEXTURE: texname = "bloomTexture"; break;
00146 case NORMAL_TEXTURE: texname = "normalTexture"; break;
00147 case BLUR_TEXTURE: texname = "blurTexture"; break;
00148
00149 default: texname = NextTexture(name + "BaseA"); break;
00150 };
00151
00153 return textures[texname].Load(texname.c_str(), textype, file, texmode, intensity, tileX, tileY, mipmap, aniso, cache);
00154 }
00155
00170 GLint TMaterial::AddTexture(const char **files, GLint textype, GLint texmode, GLfloat intensity, GLfloat tileX, GLfloat tileY, bool aniso, GLint cache)
00171 {
00172
00173 if(textype != CUBEMAP && textype != CUBEMAP_ENV)
00174 {
00175 cerr<<"ERROR: textype must be cubemap!\n";
00176 return -1;
00177 }
00178
00180 string texname = NextTexture(name + "CubeA");
00181
00183 return textures[texname].Load(texname.c_str(), textype, files, texmode, intensity, tileX, tileY, aniso, cache);
00184 }
00185
00186
00187
00194 void TMaterial::AddShadowMap(GLuint map, GLfloat intensity)
00195 {
00196
00197 if(name == "screen_quad" || !receive_shadows)
00198 return;
00199
00201 string texname = NextTexture(name + "ShadowA");
00202 textures[texname].SetID(map);
00203 textures[texname].SetName(texname);
00204 textures[texname].SetType(SHADOW);
00205
00207 if(transparency > 0.0)
00208 intensity = transparency;
00209
00210 textures[texname].SetIntensity(intensity);
00211 }
00212
00213
00219 void TMaterial::RenderMaterial(bool render_all)
00220 {
00221
00222 if(!render_all)
00223 {
00224 bool found = false;
00225 for(it = textures.begin(); it != textures.end(); it++)
00226 {
00227 if(it->second.GetType() == ALPHA)
00228 {
00229 found = true;
00230 break;
00231 }
00232 }
00233 if(!found)
00234 {
00235 glUseProgram(0);
00236 return;
00237 }
00238 }
00240
00241 if(use_gshader_ref)
00242 glUseProgram(gshader_ref);
00243 else
00244 glUseProgram(shader);
00245
00247 int i=0;
00248 for(it = textures.begin(); it != textures.end(); it++)
00249 {
00250 if(!it->second.Empty())
00251 {
00252 it->second.ActivateTexture(i);
00253 i++;
00254 }
00255 }
00256 }
00257
00264 void TMaterial::SetShadowMatrix(TMatrix &m, GLint l_num)
00265 {
00266
00267 if(name == "screen_quad")
00268 return;
00269
00270 string sh_str = name;
00271 sh_str += "Shadow";
00272
00273
00274 sh_str += num2str(char(l_num + 'A'));
00275 textures[sh_str].SetShadowMatrix(m);
00276 }
00277
00278
00290 bool TMaterial::CustomShader(const char* vert_source, const char* geom_source, const char* frag_source,
00291 const char *vert_defines, const char *frag_defines, const char *geom_defines)
00292 {
00293
00294 v_shader = glCreateShader(GL_VERTEX_SHADER);
00295 f_shader = glCreateShader(GL_FRAGMENT_SHADER);
00296
00297 string vertex_shader, fragment_shader;
00298 vertex_shader = "#version 150 compatibility\n";
00299 fragment_shader = "#version 150 compatibility\n";
00300
00301
00302 if(vert_defines != NULL)
00303 vertex_shader += vert_defines;
00304 if(frag_defines != NULL)
00305 fragment_shader += frag_defines;
00306
00307
00308 vertex_shader += LoadShader(vert_source);
00309 fragment_shader += LoadShader(frag_source);
00310
00311 if(vertex_shader == "null" || fragment_shader == "null")
00312 return false;
00313
00314 const char *ff = fragment_shader.c_str();
00315 const char *vv = vertex_shader.c_str();
00316
00317
00318 glShaderSource(v_shader, 1, &vv,NULL);
00319 glShaderSource(f_shader, 1, &ff,NULL);
00320
00321
00322 char log[BUFFER]; int len;
00323 glCompileShader(v_shader);
00324 glCompileShader(f_shader);
00325
00326
00327 shader = glCreateProgram();
00328 glAttachShader(shader,f_shader);
00329 glAttachShader(shader,v_shader);
00330
00331
00332 if(geom_source != NULL)
00333 {
00334
00335 g_shader = glCreateShader(GL_GEOMETRY_SHADER);
00336 string geometry_shader = "#version 150 compatibility\n";
00337
00338
00339 if(geom_defines != NULL)
00340 geometry_shader += geom_defines;
00341
00342 geometry_shader += LoadShader(geom_source);
00343 if(geometry_shader == "null")
00344 return false;
00345 const char *gg = geometry_shader.c_str();
00346 glShaderSource(g_shader, 1, &gg,NULL);
00347 glCompileShader(g_shader);
00348 glAttachShader(shader,g_shader);
00349 }
00350
00351
00352 glLinkProgram(shader);
00353 glUseProgram(shader);
00354
00355
00356 glGetShaderInfoLog(v_shader, BUFFER, &len, log);
00357 if(strstr(log, "succes") == NULL && len > 0)
00358 cout<<endl<<name<<":"<<log;
00359 if(geom_source != NULL)
00360 {
00361 glGetShaderInfoLog(g_shader, BUFFER, &len, log);
00362 if(strstr(log, "succes") == NULL && len > 0)
00363 cout<<endl<<name<<":"<<log;
00364 }
00365 glGetShaderInfoLog(f_shader, BUFFER, &len, log);
00366 if(strstr(log, "succes") == NULL && len > 0)
00367 cout<<endl<<name<<":"<<log;
00368
00369
00370
00372 int i=0;
00373 for(it = textures.begin(); it != textures.end(); it++)
00374 {
00375 if(!it->second.Empty())
00376 {
00377 it->second.GetUniforms(shader);
00378 it->second.ActivateTexture(i,true);
00379 i++;
00380 }
00381 }
00382 #ifdef GL3
00383
00384 glBindAttribLocation(shader, 0, "in_Vertex");
00385 glBindAttribLocation(shader, 1, "in_Normal");
00386 glBindAttribLocation(shader, 2, "in_Coord");
00387 #endif
00388
00389 gshader_ref = shader;
00390
00392 SetUniforms("material.ambient",ambColor, 3);
00393 SetUniforms("material.diffuse",diffColor, 3);
00394 SetUniforms("material.specular",specColor, 3);
00395 SetUniform("material.shininess",shininess);
00396
00397 baked = true;
00398 custom_shader = true;
00399 return true;
00400 }
00401
00402
00409 void TMaterial::SetUniform(const char* v_name, float value)
00410 {
00411 if(!glIsProgram(shader))
00412 return;
00413
00414 glUseProgram(shader);
00415 GLint loc = glGetUniformLocation(shader,v_name);
00416 if(loc < 0)
00417 return;
00418 glUniform1f(loc, value);
00419 }
00420
00427 void TMaterial::SetUniform(const char* v_name, double value)
00428 {
00429 if(!glIsProgram(shader))
00430 return;
00431
00432 glUseProgram(shader);
00433 GLint loc = glGetUniformLocation(shader,v_name);
00434 if(loc < 0)
00435 return;
00436 glUniform1f(loc, (float)value);
00437 }
00438
00445 void TMaterial::SetUniform(const char* v_name, int value)
00446 {
00447 if(!glIsProgram(shader))
00448 return;
00449
00450 glUseProgram(shader);
00451 GLint loc = glGetUniformLocation(shader,v_name);
00452 if(loc < 0)
00453 return;
00454 glUniform1i(loc, value);
00455 }
00456
00463 void TMaterial::SetUniforms(const char* v_name, float *value, int values)
00464 {
00465 if(!glIsProgram(shader))
00466 return;
00467
00468 glUseProgram(shader);
00469 GLint loc = glGetUniformLocation(shader,v_name);
00470 if(loc < 0)
00471 return;
00472
00473
00474 switch(values)
00475 {
00476 case 2: glUniform2fv(loc, 1, value); break;
00477 case 3: glUniform3fv(loc, 1, value); break;
00478 case 4: glUniform4fv(loc, 1, value); break;
00479 case 9: glUniformMatrix3fv(loc, 1, 0, value); break;
00480 case 16: glUniformMatrix4fv(loc, 1, 0, value); break;
00481 default: break;
00482 }
00483 }