src/RefractiveShader.h

Go to the documentation of this file.
00001 #ifndef REFRACTIVESHADER_H
00002 #define REFRACTIVESHADER_H
00003 
00004 #include "Shader.h"
00005 #include "Scene.h"
00006 #include "Texture.h"
00007 #include "Ray.h"
00008 #include "Vec3f.h"
00009 #include "defines.h"
00010 
00011 
00017 class RefractiveShader : public Shader
00018 {
00019 public:
00026     RefractiveShader(   Scene *             scene,
00027                         const RGBAColor &   color,
00028                         float               refractionIdx );
00029 
00032     RGBAColor shade(const Ray & ray) const
00033     {
00034         assert(ray.hit());
00035         assert(ray.obj());
00036 
00037         // adaptive recursion termination
00038         if (ray.influence() < MIN_INFLUENCE || ray.recDeep() > MAX_RECURSION_DEEP)
00039         {
00040             // let rays with small influence out of the refractive object
00041             Ray newray;
00042             newray.init(ray.hitPoint(EPSILON), ray.dir());
00043             newray.updateInfluence(ray);
00044             return mScene->rayTrace(newray);
00045 //            return RGBAColor(0, 1, 0);  // DEBUG
00046         }
00047 
00048         // normal of the surface
00049         Vec3f n = normal(ray);
00050 
00051         // compute cosine of incident ray
00052         float cosIncident = n.dot(-ray.dir());
00053         bool fromOutside = cosIncident >= 0;
00054         // use inverted refraction index for rays coming from outside
00055         float refIdx = mRefractionIndex;
00056         if (fromOutside)
00057             refIdx = mInvRefractionIndex;
00058         // cosine of refracted ray with Snell's law
00059         float sqrCosRefracted = 1.0f - refIdx*refIdx*(1.0f - cosIncident*cosIncident);
00060 
00061         // reflected vector
00062         Vec3f reflected = ray.dir() + 2*cosIncident*n;
00063         Ray newray;
00064 
00065         // Fresnel coefficients
00066         float R  = 1.0f;
00067 
00068         Vec3f refractedCol;
00069         if (sqrCosRefracted >= 0.0f)
00070         {
00071             // refraction
00072             float cosRefracted = sqrtf(sqrCosRefracted);
00073             // Fresnel coefficients
00074             float Rs = 0.0f;
00075             float Rp = 0.0f;
00076             // refracted vector
00077             Vec3f v = refIdx*ray.dir();
00078             if (fromOutside)
00079             {
00080                 v += (refIdx*cosIncident - cosRefracted)*n;
00081             }
00082             else
00083             {
00084                 cosIncident = - cosIncident;
00085                 v -= (refIdx*cosIncident - cosRefracted)*n;
00086             }
00087 
00088             Rs = (cosIncident - mRefractionIndex*cosRefracted)/(cosIncident + mRefractionIndex*cosRefracted);
00089             Rp = (cosRefracted - mRefractionIndex*cosIncident)/(cosRefracted + mRefractionIndex*cosIncident);
00090             // reflection coefficient for unpolarised light
00091             R = (Rs*Rs + Rp*Rp)*0.5;
00092 
00093             // trace in the refracted direction
00094             newray.init(ray.hitPoint(EPSILON), v);
00095             newray.updateInfluence(ray, 1.0f - R);
00096             refractedCol = mScene->rayTrace(newray).rgb();
00097             if (fromOutside)
00098             {
00099                 float shading = powf(1.0f - mColor.a(), newray.t());    // shade with material thickness
00100                 refractedCol = lerp(mColor.rgb(), refractedCol, shading);
00101             }
00102         }
00103         // else total reflection
00104         assert(0 <= R && R <= 1);
00105 
00106         // trace in the reflected direction
00107         newray.init(ray.hitPoint(-EPSILON), reflected);
00108         newray.updateInfluence(ray, R);
00109         Vec3f reflectedCol = mScene->rayTrace(newray).rgb();
00110         if (!fromOutside)
00111         {
00112             float shading = powf(1.0f - mColor.a(), newray.t());    // material thickness
00113             reflectedCol = lerp(mColor.rgb(), reflectedCol, shading);
00114         }
00115 
00116         // interpolate resulted color
00117         return RGBAColor(lerp(refractedCol, reflectedCol, R));
00118     }
00119 
00120 private:
00122     RGBAColor   mColor;
00123 
00125     float       mRefractionIndex;
00126 
00128     float       mInvRefractionIndex;
00129 };
00130 
00131 
00132 #endif
00133 

Generated on Fri Feb 1 00:01:42 2008 for Grayfall by  doxygen 1.5.1