BumpMappedWoodPhongShader.h

Go to the documentation of this file.
00001 #ifndef BUMPMAPPEDWOODPHONGSHADER_H
00002 #define BUMPMAPPEDWOODPHONGSHADER_H BUMPMAPPEDWOODPHONGSHADER_H
00003 
00004 #include "Shader.h"
00005 #include "WoodShader.h"
00006 
00007 class BumpMappedWoodPhongShader : public Shader
00008 {
00009 public:
00010     ColorRGBA color; // base color
00011     float ka;    // ambient coefficient
00012     float kd;    // diffuse reflection coefficients
00013     float ks;    // specular refelection coefficients
00014     float ke;    // shininess exponent
00015    
00016     Texture* bumpmap;
00017     float bumpfactor;
00018     
00019     Shader* wood;
00020 
00021     BumpMappedWoodPhongShader(Scene *scene,
00022             ColorRGBA color, float ka,float kd, float ks, float ke, Texture* bumpmap, float bumpfactor, Vector3D center)
00023     : Shader(scene),color(color),ka(ka),kd(kd),ks(ks),ke(ke),bumpmap(bumpmap),bumpfactor(bumpfactor)
00024     {
00025         wood = new WoodShader(scene, center, 3);
00026     };
00027 
00028     ~BumpMappedWoodPhongShader () {
00029         delete wood;
00030     }
00031     
00032     virtual ColorRGBA Shade(Ray &ray)
00033     {
00034         // get shading normal
00035         Vector3D normal = ray.hit->GetNormal(ray);
00036     
00037         // turn normal to front
00038         if (Dot(normal,ray.dir) > 0)
00039             normal = -normal;
00040        
00041         // get bump value, we need only one float between 0 and 1,
00042         // we use the greyscale
00043         ColorRGBA bump = bumpmap->GetTexel(ray.hit->GetUV(ray));
00044         
00045         // compute new normal
00046         // see "Texturing & Modeling, a Modern Approach", chapter 2
00047         Vector3D p = ray.org + ray.t * ray.dir;
00048         Vector3D du = p + Cross(normal, normal + Vector3D(0,0,1)).Normalized();
00049         Vector3D dv = p + Cross(normal, du).Normalized();
00050         p += bumpfactor * bump.average() * normal;
00051         du = p - du;
00052         dv = p - dv;
00053         normal = Cross(du, dv).Normalized();
00054 
00055         // turn normal to front
00056         if (Dot(normal,ray.dir) > 0)
00057             normal = -normal;
00058        
00059         // calculate reflection vector
00060         Vector3D reflect = ray.dir - 2*Dot(normal,ray.dir)*normal;
00061         
00062         // ambient term
00063         ColorRGBA ambientColor = ka * color;
00064         ColorRGBA result = ambientColor;
00065         
00066         // shadow ray (up to now only for the light direction)    
00067         Ray shadow;
00068         shadow.org = ray.org + ray.t * ray.dir;
00069         
00070         // iterate over all light sources
00071         for (unsigned int l=0; l < scene->mLights.size(); l++)
00072         {      
00073             // get direction to light, and intensity 
00074             ColorRGBA lightIntensity;
00075             ColorRGBA result_local = ColorRGBA(0.0);
00076 
00077             // check whenever the shader is computing area light source
00078             for(unsigned int s = 0; s < scene->mLights[l]->GetNumberOfRays(); s++)
00079             {
00080                 // illuminate the ray by the light source
00081                 if (scene->mLights[l]->Illuminate(shadow, lightIntensity, s))
00082                 {   
00083                         // compute distance to the light source 
00084                         float distance = shadow.t;
00085         
00086                         // diffuse term, also used as a check if illuminating the front-side
00087                         float cosLightNormal = Dot(shadow.dir,normal);
00088                         if (cosLightNormal > 0)
00089                         {
00090                             // if the ray is occluded, hence there is a shadow
00091                             // we put this here to optimize all things, since we work only for in-front surfaces
00092                             if (scene->castShadows && scene->Intersect(shadow) && shadow.hit->castShadows())
00093                             {
00094                                 // if the shadow ray intersects a surface which is near then the light source, then we 
00095                                 // are in shadow
00096                                 if (shadow.t < distance)
00097                                     continue;
00098                             }
00099         
00100                             // compute diffuse term             
00101                             ColorRGBA diffuseColor = kd * color;
00102                             result_local = result_local + (diffuseColor * cosLightNormal) * lightIntensity;
00103                 
00104                             // specular term is computed only if shading the front-side
00105                             float cosLightReflect = Dot(shadow.dir,reflect);
00106                             if (cosLightReflect > 0)
00107                             {
00108                                 ColorRGBA specularColor = ks * ColorRGBA(1,1,1); // white highlight;
00109                                 result_local = result_local + (specularColor * powf(cosLightReflect,ke)) * lightIntensity;
00110                             }
00111                         }
00112                 }
00113             }   
00114             
00115             result_local.red() /= float(scene->mLights[l]->GetNumberOfRays());
00116             result_local.green() /= float(scene->mLights[l]->GetNumberOfRays());
00117             result_local.blue() /= float(scene->mLights[l]->GetNumberOfRays());
00118             result += result_local;
00119         }
00120         
00121         // make surface woody
00122         result *= wood->Shade(ray);
00123 
00124         return result;
00125     };
00126 };
00127 
00128 #endif

Generated on Thu Jan 31 21:48:48 2008 for RayTracer by  doxygen 1.5.4