00001
00005 #include "material.h"
00006
00007
00014 string LoadFunc(char* func)
00015 {
00016 string file;
00017 file += "data/shaders/func/";
00018 file += func;
00019 file += ".shad";
00020 ifstream fin(file.c_str());
00021 if(!fin)
00022 return "null";
00023 string data;
00024 char ch;
00025 while(fin.get(ch))
00026 data+=ch;
00027
00028 return data;
00029 }
00030
00031
00033
00035
00043 string computeTexel(Texture &t, string name)
00044 {
00045 string ret = "\n";
00046
00047
00048 if(t.GetType() == ENV)
00049 ret += " " + name + "_texture = envMapping(color,eyeVec,normal," + name + ", " + name + "_intensity);\n";
00050
00051 else if(t.GetType() == CUBEMAP)
00052 ret += " " + name + "_texture = textureCube(" + name + ", " + name + "_cubeCoords);\n";
00053
00054 else if(t.GetType() == CUBEMAP_ENV)
00055 ret += " " + name + "_texture = textureCube(" + name + ", reflVec);\n";
00056
00057 else
00058 ret += " " + name + "_texture = texture2D(" + name + ", " + name + "_texcoord);\n";
00059
00060 switch(t.GetMode())
00061 {
00063 case ADD:
00064 ret +=
00065 " //" + name + ", ADD mode\n"
00066 " color.rgb += " + name + "_texture.rgb;\n"
00067 " color.a *= " + name + "_texture.a;\n"
00068 " color = clamp (color, 0.0, 1.0);\n";
00069 break;
00071 case MODULATE:
00072 ret +=
00073 " //" + name + ", MODULATE mode\n"
00074 " color *= " + name + "_texture;\n";
00075 break;
00077 case DECAL:
00078 ret +=
00079 " //" + name + ", DECAL mode\n"
00080 " color = vec4(mix(color.rgb, " + name + "_texture.rgb, " + name + "_texture.a), color.a);\n";
00081 break;
00083 case BLEND:
00084 ret +=
00085 " //" + name + ", BLEND mode\n"
00086 " color = vec4 ( vec3(mix(color.rgb, gl_TextureEnvColor[0].rgb, " + name + "_texture.rgb)), color.a * " + name + "_texture.a);\n";
00087 break;
00089 case REPLACE:
00090 ret +=
00091 " //" + name + ", REPLACE mode\n"
00092 " color = " + name + "_texture;\n";
00093 break;
00094 };
00095 return ret;
00096 }
00097
00104 bool TMaterial::BakeMaterial(bool use_geom)
00105 {
00106
00107 if(custom_shader)
00108 return true;
00109
00110 string tmp = name;
00111
00112
00113 string g_pref;
00114 if(use_geom)
00115 g_pref = "v_";
00116
00120
00122 string vert_vars = "//GLSL vertex shader generated by gluxEngine\n";
00123 vert_vars += "//Material: \"" + name + "\"\n\n";
00124 #ifdef GL3
00125 vert_vars +=
00126 "//generic vertex attributes\n"
00127 "in vec3 in_Vertex;\n"
00128 "in vec3 in_Normal;\n"
00129 "in vec2 in_Coord;\n\n";
00130 #else
00131 vert_vars +=
00132 "//built-in vertex attributes\n"
00133 "vec3 in_Vertex = gl_Vertex.xyz;\n"
00134 "vec3 in_Normal = gl_Normal;\n"
00135 "vec2 in_Coord = gl_MultiTexCoord0.st;\n\n";
00136 #endif
00137 vert_vars += "//texture coordinate\n";
00138
00139 if(use_geom)
00140 vert_vars += "out vec2 geomTexCoord;\n";
00141 else
00142 vert_vars += "out vec2 fragTexCoord;\n";
00143
00144 string vert_func;
00145
00146 string vert_main =
00147 "\nvoid main()\n"
00148 "{\n"
00149 " vec4 vertex = vec4(in_Vertex,1.0);\n"
00150 " vec3 dNormal = in_Normal;\n";
00151
00153 bool displace = false;
00154 for(it = textures.begin(); it != textures.end(); it++)
00155 {
00156 if(it->second.GetType() == DISPLACE)
00157 {
00158 string texname = it->second.GetName();
00159
00160 if(it->second.HasTiles())
00161 vert_vars += "uniform float " + texname + "_tileX, " + texname + "_tileY;\n";
00162 vert_vars += "uniform float " + texname + "_intensity;\n"
00163 "uniform sampler2D "+ texname + ";\n";
00164 vert_main += " //displace vertex\n";
00165
00166 if(it->second.HasTiles())
00167 vert_main += " vec4 dv = texture2DLod(" + texname + ", in_Coord*vec2(" + texname + "_tileX, " + texname + "_tileY), 0.0);\n";
00168
00169 else
00170 vert_main += " vec4 dv = texture2DLod(" + texname + ", in_Coord, 0.0);\n";
00171
00172 vert_main += " float displace = dv.r; //dot( vec4(0.30,0.59,0.11,0.0),dv);\n"
00173 " vertex.xyz += " + texname + "_intensity * displace * in_Normal;\n";
00174 displace = true;
00175 break;
00176 }
00177 }
00178
00179 if(displace)
00180 {
00181 for(it = textures.begin(); it != textures.end(); it++)
00182 {
00183 if(it->second.GetType() == BUMP)
00184 {
00185 string texname = it->second.GetName();
00186 if(it->second.HasTiles())
00187 vert_vars += "uniform float " + texname + "_tileX, " + texname + "_tileY;\n";
00188 vert_vars += "uniform float " + texname + "_intensity;\n"
00189 "uniform sampler2D "+ texname + ";\n";
00190 vert_main += " //displace normal using normal map\n";
00191
00192 if(it->second.HasTiles())
00193 vert_main += " dNormal += normalize(texture2D(" + texname + ",in_Coord*vec2(" + texname + "_tileX, " + texname + "_tileY)).rgb * 2.0 - 1.0);\n\n";
00194
00195 else
00196 vert_main += " dNormal += normalize(texture2D(" + texname + ",in_Coord).rgb * 2.0 - 1.0);\n\n";
00197 break;
00198 }
00199 }
00200 }
00201
00202
00203
00205
00206 tmp += "Env";
00208 if(lightModel == PHONG || textures.find(tmp) != textures.end() )
00209 {
00210 vert_vars += "out vec3 " + g_pref + "normal, " + g_pref + "eyeVec;\n";
00211
00212 vert_main +=
00213 " " + g_pref + "normal = gl_NormalMatrix * dNormal; //surface normal\n"
00214 " vec3 vVertex = vec3(gl_ModelViewMatrix * vertex); //view vector\n"
00215 " " + g_pref + "eyeVec = -vVertex; //eyeview position\n";
00216 }
00217
00219 else if(lightModel == GOURAUD)
00220 {
00222 vert_vars += "out vec4 " + g_pref + "v_color;\n" +
00223 "out vec3 " + g_pref + "normal," + g_pref + "eyeVec;\n";
00224
00225 vert_func += LoadFunc("light");
00226 vert_main +=
00227 " " + g_pref + "normal = gl_NormalMatrix * dNormal; //surface normal\n"
00228 " vec3 vVertex = vec3(gl_ModelViewMatrix * vertex); //view vector\n"
00229 " " + g_pref + "eyeVec = -vVertex; //eyeview position\n"
00230 " " + g_pref + "v_color = LightModel(" + g_pref + "normal," + g_pref + "eyeVec); //calculate light model\n";
00231 }
00232
00233 else
00234 {
00235 vert_vars += "out vec3 normal;\n";
00236 vert_main += " normal = gl_NormalMatrix * dNormal; //surface normal\n";
00237 }
00238
00239
00240
00241
00243 if(use_geom)
00244 vert_main += " geomTexCoord = in_Coord;\n";
00245 else
00246 vert_main += " fragTexCoord = in_Coord;\n";
00247
00248
00249
00250
00251 for(it = textures.begin(); it != textures.end(); it++)
00252 {
00254 if(it->second.GetType() == SHADOW)
00255 {
00256 vert_vars += "out vec4 " + g_pref + it->first + "_projShadow;\n";
00257 vert_vars += "uniform mat4 " + it->first + "_texMatrix;\n";
00258 vert_main += " " + g_pref + it->first + "_projShadow = " + it->first + "_texMatrix * gl_ModelViewMatrix * vertex; //calculate shadow texture projection\n";
00259 }
00260
00262 if(it->second.GetType() == CUBEMAP)
00263 {
00264 vert_vars += "out vec3 " + g_pref + it->first + "_cubeCoords;\n";
00265 vert_main += " " + it->first + "_cubeCoords = vertex.xyz;\n";
00266 }
00267
00269 if(it->second.GetType() == CUBEMAP_ENV)
00270 {
00271 vert_vars += "out vec3 " + g_pref + "r_normal," + g_pref + "r_eyeVec;\n";
00272 vert_main +=
00273 "\n //Camera rotation can be found in transposed modelview matrix\n"
00274 " mat3 tcamerarot;\n"
00275 " tcamerarot[0][0] = gl_ModelViewMatrixTranspose[0][0];\n"
00276 " tcamerarot[0][1] = gl_ModelViewMatrixTranspose[0][1];\n"
00277 " tcamerarot[0][2] = gl_ModelViewMatrixTranspose[0][2];\n"
00278 " tcamerarot[1][0] = gl_ModelViewMatrixTranspose[1][0];\n"
00279 " tcamerarot[1][1] = gl_ModelViewMatrixTranspose[1][1];\n"
00280 " tcamerarot[1][2] = gl_ModelViewMatrixTranspose[1][2];\n"
00281 " tcamerarot[2][0] = gl_ModelViewMatrixTranspose[2][0];\n"
00282 " tcamerarot[2][1] = gl_ModelViewMatrixTranspose[2][1];\n"
00283 " tcamerarot[2][2] = gl_ModelViewMatrixTranspose[2][2];\n\n"
00284 "\n //Coordinates for cubemap reflexion\n"
00285 " " + g_pref + "r_normal = tcamerarot * (gl_NormalMatrix * dNormal);\n"
00286 " " + g_pref + "r_eyeVec = tcamerarot * (gl_ModelViewMatrix * vertex).xyz;\n\n";
00287 }
00288 }
00289
00290
00292
00293 if(use_geom)
00294 vert_main +=
00295 " gl_Position = gl_ModelViewMatrix * vertex; //vertex transform will be done in geometry shader\n"
00296 "}\n"
00297 "\n";
00298 else
00299 vert_main +=
00300 " gl_Position = gl_ModelViewProjectionMatrix * vertex; //vertex transform\n"
00301 "}\n"
00302 "\n";
00303
00304 string vertex_shader = "#version 150 compatibility\n";
00305 vertex_shader += vert_vars + vert_func + vert_main;
00306
00307
00308
00312
00313 string geom_vars, geom_func, geom_main;
00314
00315 if(use_geom)
00316 {
00318 geom_vars = "//GLSL geometry shader generated by gluxEngine\n"
00319 "#extension GL_EXT_geometry_shader4: enable\n"
00320 "#extension GL_EXT_gpu_shader4: enable\n"
00321 "layout(triangles) in;\n"
00322 "layout(max_vertices=32) out;\n\n";
00323
00324 geom_vars += "//Material: \"" + name + "\"\n\n";
00325 geom_func = LoadFunc("matrices");
00326
00327
00328
00329 geom_main += LoadFunc("gref_main");
00330
00331
00333
00334 tmp += "Env";
00336 if(lightModel == PHONG || textures.find(tmp) != textures.end() )
00337 {
00338 geom_vars += "in vec3 v_normal[], v_eyeVec[];\n"
00339 "out vec3 normal, eyeVec;\n";
00340
00341 geom_main +=
00342 " normal = v_normal[i];\n"
00343 " eyeVec = v_eyeVec[i];\n";
00344 }
00345
00346
00347 if(lightModel == GOURAUD)
00348 {
00349 geom_vars += "in vec4 v_v_color[];\nout vec4 v_color;";
00350 geom_main += " v_color = v_v_color[i];\n";
00351 }
00352
00353
00354
00355 for(it = textures.begin(); it != textures.end(); it++)
00356 {
00358 if(it->second.GetType() == SHADOW)
00359 {
00360 geom_vars += "in vec4 v_" + it->first + "_projShadow[];\n" +
00361 "out vec4 " + it->first + "_projShadow;\n";
00362 geom_main += " " + it->first + "_projShadow = v_" + it->first + "_projShadow[i];\n";
00363 }
00364
00366 if(it->second.GetType() == CUBEMAP)
00367 {
00368 geom_vars += "in vec3 v_" + it->first + "_cubeCoords[];\n" +
00369 "out vec3 " + it->first + "_cubeCoords;\n";
00370 geom_main += " " + it->first + "_cubeCoords = v_" + it->first + "_cubeCoords[i];\n";
00371 }
00372
00374 if(it->second.GetType() == CUBEMAP_ENV)
00375 {
00376 geom_vars += "in vec3 v_r_normal[], v_r_eyeVec[];\n"
00377 "out vec3 r_normal, r_eyeVec;\n";
00378 geom_main +=
00379 " r_normal = v_r_normal[i];\n"
00380 " r_eyeVec = v_r_eyeVec[i];\n";
00381 }
00382 }
00383
00384 geom_main +=
00385 " EmitVertex();\n"
00386 " }\n"
00387 " EndPrimitive();\n"
00388 " }\n"
00389 "}\n";
00390 }
00391 string geometry_shader = "#version 150 compatibility\n";
00392 geometry_shader += geom_vars + geom_func + geom_main;
00393
00394
00395
00396
00397
00401
00403 string frag_vars = "//GLSL fragment shader generated by gluxEngine\n\n";
00404 frag_vars += "//Material: \"" + name + "\"\n\n"
00405 "//texture coordinate\n";
00406 frag_vars += "in vec2 fragTexCoord;\n";
00407
00408 if(useMRT)
00409 frag_vars += "out vec4 out_FragData[2];\n\n";
00410 else
00411 frag_vars += "out vec4 out_FragColor;\n\n";
00412
00413 string frag_func;
00414 string frag_main = "\nvoid main()\n{\n";
00415
00416
00417
00419 frag_main += " vec2 texCoord = fragTexCoord;\n";
00420
00421
00422 for(it = textures.begin(); it != textures.end(); it++)
00423 {
00424 if(it->second.GetType() == PARALLAX)
00425 {
00426 string offset;
00427 offset = num2str(it->second.intensity);
00428 frag_main +=
00429 " //simple parallax mapping, modify texture coordinates\n"
00430 " float height = texture2D(" + name + "ParallaxA, texCoord).r;\n"
00431 " float offset = " + offset + " * (2.0 * height - 1.0);\n"
00432 " texCoord = texCoord + eyeVec.xy * offset;\n\n";
00433 break;
00434 }
00435 }
00436
00437 for(it = textures.begin(); it != textures.end(); it++)
00438 {
00439 if(!it->second.Empty() && it->second.GetType() != SHADOW && it->second.GetType() != DISPLACE )
00440 {
00441 frag_main +=
00442 "\n vec4 " + it->first + "_texture;\n";
00443
00444
00445 if(it->second.GetType() == CUBEMAP)
00446 frag_vars += "uniform samplerCube "+ it->first + ";\n"
00447 "in vec3 " + it->first + "_cubeCoords;\n\n";
00448
00449 else if(it->second.GetType() == CUBEMAP_ENV)
00450 frag_vars += "uniform samplerCube "+ it->first + ";\n"
00451 "in vec3 r_normal, r_eyeVec;\n\n";
00452
00453 else
00454 {
00455
00456 frag_vars += "uniform float " + it->first + "_intensity;\n";
00457
00458 if(it->second.HasTiles())
00459 {
00460 frag_vars += "uniform float " + it->first + "_tileX," + it->first + "_tileY;\n";
00461 frag_main +=
00462 " //" + it->first + ", texture tiles\n"
00463 " vec2 " + it->first + "_texcoord = texCoord * vec2(" + it->first + "_tileX, " + it->first + "_tileY) ;\n";
00464 }
00465
00466 else
00467 frag_main += " vec2 " + it->first + "_texcoord = texCoord;\n";
00468
00469 frag_vars += "uniform sampler2D "+ it->first + ";\n";
00470 }
00471 }
00472 }
00473
00474
00475
00477 if(lightModel == PHONG)
00478 {
00479 frag_vars += "in vec3 normal, eyeVec;\n"
00480 "//material properties\n"
00481 "in vec4 diff, spec;\n"
00482 "in float shin;\n";
00483 frag_func += LoadFunc("light");
00484
00486 tmp = name; tmp += "BumpA";
00487 if( textures.find(tmp) != textures.end() )
00488 {
00489 frag_main +=
00490 " //bump-mapping\n"
00491 " vec3 bump_normal = normal + normalize(texture2D(" + name + "BumpA, " + tmp + "_texcoord).xyz*2.0 - " + name + "BumpA_intensity);\n"
00492 " vec4 color = LightModel(bump_normal,eyeVec);\n";
00493 }
00494 else
00495 frag_main +=" vec4 color = LightModel(normal,eyeVec);\n";
00496 }
00498 else if(lightModel == GOURAUD)
00499 {
00500 frag_vars += "in vec4 v_color;\n"
00501 "in vec3 normal;\n";
00502 frag_main += " vec4 color = v_color;\n";
00503 }
00505 else
00506 {
00507 frag_vars += "in vec3 normal;\n\n"
00508 "//material settings (only diffuse)\n"
00509 "struct Material{\n"
00510 " vec3 diffuse;\n};\n"
00511 "uniform Material material;\n";
00512 frag_main += " vec4 color = vec4(material.diffuse,0.0);\n";
00513 }
00514
00515
00516
00518 string alpha_test = "";
00519 for(it = textures.begin(); it != textures.end(); it++)
00520 {
00521 if(!it->second.Empty())
00522 {
00523
00524 if(it->second.GetType() == DISPLACE)
00525 continue;
00527 else if(it->second.GetType() == SHADOW)
00528 {
00529 frag_vars += "in vec4 " + it->first + "_projShadow;\n";
00530 frag_vars +=
00531 "uniform float " + it->first + "_intensity;\n"
00532 "uniform sampler2DShadow " + it->first + ";\n";
00533
00534
00535 if(it->first.find("ShadowA") != string::npos)
00536 frag_func += LoadFunc("shadow");
00537
00538 frag_main += "\n //Shadow map projection\n"
00539 " color *= PCFShadow(" + it->first + "," + it->first + "_projShadow, " + it->first + "_intensity);\n";
00540 }
00541
00542 else
00543 {
00544
00545 if(it->second.GetType() == ALPHA)
00546 alpha_test = " //alpha test\n if( all(lessThan(" + it->first + "_texture.rgb, vec3(0.25)))) discard;\n";
00548 if(it->second.GetType() == ENV)
00549 {
00550
00551 if(it->first.find("EnvB") == string::npos)
00552 {
00553
00554 if(lightModel != PHONG)
00555 frag_vars += "in vec3 eyeVec;\n";
00556
00557 frag_func += LoadFunc("env");
00558 }
00559 }
00560
00561
00562 if(it->second.GetType() == CUBEMAP_ENV)
00563 frag_main += " vec3 reflVec = reflect(normalize(r_eyeVec), normalize(r_normal)); //reflection vector for cubemap\n";
00564
00565
00566 if(it->second.GetType() != BUMP && it->second.GetType() != PARALLAX)
00567 frag_main += computeTexel(it->second,it->first);
00568
00569 }
00570 }
00571 }
00572
00573
00574
00576 frag_main +=
00577 "\n //FINAL fragment color\n";
00578
00579
00580 if(transparency > 0.0)
00581 {
00582 string trans;
00583 trans = num2str(transparency);
00584 frag_main += " out_FragColor = vec4(vec3(color.rgb), ";
00585 frag_main += trans;
00586 frag_main += ");\n";
00587 }
00588
00589 else if(useMRT)
00590 frag_main += " out_FragData[0].rgb = color.rgb; //color;\n"
00591 " out_FragData[1].rgb = normal; //normal;\n"
00592 " out_FragData[1].a = pow(gl_FragCoord.z,128.0); //depth;\n";
00593 else
00594 {
00595
00596 frag_main += alpha_test + " out_FragColor = color;\n";
00597 }
00598
00599 frag_main +=
00600 "}\n"
00601 "\n";
00602 string frag_shader = "#version 150 compatibility\n";
00603 frag_shader += frag_vars + frag_func + frag_main;
00604
00606
00607
00608
00609 string file; file = "shader_out/" + name + ".vert";
00610 ofstream fout1(file.c_str());
00611 fout1<<vertex_shader;
00612 file = "shader_out/" + name + ".frag";
00613 ofstream fout2(file.c_str());
00614 fout2<<frag_shader;
00615
00617 v_shader = glCreateShader(GL_VERTEX_SHADER);
00618 f_shader = glCreateShader(GL_FRAGMENT_SHADER);
00619
00620
00621 const char *ff = frag_shader.c_str();
00622 const char *vv = vertex_shader.c_str();
00623
00624
00625 glShaderSource(v_shader, 1, &vv,NULL);
00626 glShaderSource(f_shader, 1, &ff,NULL);
00627
00628
00629 char log[BUFFER]; int len;
00630 glCompileShader(v_shader);
00631 glCompileShader(f_shader);
00632
00633
00634 GLuint tmp_shader = glCreateProgram();
00635 glAttachShader(tmp_shader,f_shader);
00636 glAttachShader(tmp_shader,v_shader);
00637
00638
00639 if(use_geom)
00640 {
00641 file = "shader_out/" + name + ".geom";
00642 ofstream fout3(file.c_str());
00643 fout3<<geometry_shader;
00644
00645 g_shader = glCreateShader(GL_GEOMETRY_SHADER);
00646 const char *gg = geometry_shader.c_str();
00647 glShaderSource(g_shader, 1, &gg,NULL);
00648 glCompileShader(g_shader);
00649 glAttachShader(tmp_shader,g_shader);
00650 }
00651 glLinkProgram(tmp_shader);
00652 glUseProgram(tmp_shader);
00653
00654
00655
00656 glGetShaderInfoLog(v_shader, BUFFER, &len, log);
00657 if(strstr(log, "succes") == NULL && len > 0)
00658 cout<<endl<<name<<":"<<log;
00659 if(use_geom)
00660 {
00661 glGetShaderInfoLog(g_shader, BUFFER, &len, log);
00662 if(strstr(log, "succes") == NULL && len > 0)
00663 cout<<endl<<name<<":"<<log;
00664 }
00665 glGetShaderInfoLog(f_shader, BUFFER, &len, log);
00666 if(strstr(log, "succes") == NULL && len > 0)
00667 cout<<endl<<name<<":"<<log;
00668
00669
00670
00672 int i=0;
00673 for(it = textures.begin(); it != textures.end(); it++)
00674 {
00675 if(!it->second.Empty())
00676 {
00677 it->second.GetUniforms(tmp_shader);
00678 it->second.ActivateTexture(i,true);
00679 i++;
00680 }
00681 }
00682
00683 #ifdef GL3
00684
00685 glBindAttribLocation(tmp_shader, 0, "in_Vertex");
00686 glBindAttribLocation(tmp_shader, 1, "in_Normal");
00687 glBindAttribLocation(tmp_shader, 3, "in_Coord");
00688 #endif
00689
00690 if(use_geom)
00691 gshader_ref = tmp_shader;
00692 else
00693 shader = tmp_shader;
00694
00696 SetUniforms("material.ambient",ambColor, 3);
00697 SetUniforms("material.diffuse",diffColor, 3);
00698 SetUniforms("material.specular",specColor, 3);
00699 SetUniform("material.shininess",shininess);
00700
00701 baked = true;
00702
00703 return true;
00704 }