BumpMappedPhongShader.h

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

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