1 #ifndef TRANSPARENCY_HXX
  2 #define TRANSPARENCY_HXX
  3 
  4 #include "PhongShader.hxx"
  5 
  6 class TransparencyShader : public Shader
  7 {
  8     private:
  9         Vec3f color;            // base color
 10         float ka;               // ambient coefficient
 11         float kd;               // diffuse reflection coefficients
 12         float ks;               // specular refelection coefficients
 13         float ke;               // shininess exponent   
 14         float reflection;       // reflection coefficient
 15         float transparency;     // transmisson coefficient
 16         float n1, n2;           // refraction coefficients: n1 of first medium, n2 of second medium 
 17         
 18     public:
 19         TransparencyShader(Scene *scene, Vec3f color, float ka, float kd, float ks, float ke, 
 20                            float reflection, float transparency, float n1, float n2 )
 21         : Shader(scene),color(color),ka(ka),kd(kd),ks(ks),ke(ke),reflection(reflection), transparency(transparency), n1(n1), n2(n2)
 22         {};
 23         
 24         ~TransparencyShader()
 25         {};
 26         
 27         void setTransparency(float t)
 28         {
 29             transparency = t;
 30         }
 31 
 32         virtual Vec3f Shade(Ray &ray)
 33         {
 34             /**
 35              * some basic calculation
 36              */
 37                 Vec3f normal = ray.hit->GetNormal(ray);
 38                 Vec3f hitpoint = ray.org + ray.t * ray.dir;
 39 
 40                 float refraction_temp = n1 / n2;    
 41                     
 42                 if (Dot(normal,ray.dir) > 0)
 43                 {
 44                     normal = -normal;
 45                     refraction_temp = n2 / n1;
 46                 }
 47             
 48             /********************* normal PhongShader procedure begin *********************/
 49             // calculate reflection vector
 50             Vec3f reflect = ray.dir - 2*Dot(normal,ray.dir)*normal;
 51             
 52             // ambient term
 53             Vec3f ambientIntensity(1,1,1);
 54             Vec3f ambientColor = ka * color;
 55             Vec3f result = Product(ambientColor, ambientIntensity);
 56             
 57             // shadow ray (up to now only for the light direction)    
 58             Ray shadow;
 59             shadow.org = ray.org + ray.t * ray.dir;
 60             
 61             // iterate over all light sources
 62             for (unsigned int l=0; l < scene->mLights.size(); l++)
 63             {      
 64                 // get direction to light, and intensity 
 65                 Vec3f lightIntensity;
 66                 Vec3f result_local = Vec3f(0.0);
 67 
 68                 // check whenever the shader is computing area light source
 69                 for(unsigned int s = 0; s < scene->mLights[l]->GetNumberOfRays(); s++)
 70                 {
 71                     // illuminate the ray by the light source
 72                     if (scene->mLights[l]->Illuminate(shadow, lightIntensity, s))
 73                     {   
 74                         // compute distance to the light source 
 75                         float distance = shadow.t;
 76         
 77                         // diffuse term, also used as a check if illuminating the front-side
 78                         float cosLightNormal = Dot(shadow.dir,normal);
 79                         if (cosLightNormal > 0)
 80                         {
 81                             // if the ray is occluded, hence there is a shadow
 82                             // we put this here to optimize all things, since we work only for in-front surfaces
 83                             if (scene->castShadows && scene->Intersect(shadow) && shadow.hit->castShadows())
 84                             {
 85                                 // if the shadow ray intersects a surface which is near then the light source, then we 
 86                                 // are in shadow
 87                                 if (shadow.t < distance)
 88                                     continue;
 89                             }
 90         
 91                             // compute diffuse term             
 92                             Vec3f diffuseColor = kd * color;
 93                             result_local = result_local + Product(diffuseColor * cosLightNormal, lightIntensity);
 94                 
 95                             // specular term is computed only if shading the front-side
 96                             float cosLightReflect = Dot(shadow.dir,reflect);
 97                             if (cosLightReflect > 0)
 98                             {
 99                                 Vec3f specularColor = ks * Vec3f(1,1,1); // white highlight;
100                                 result_local = result_local + Product(specularColor * powf(cosLightReflect,ke), lightIntensity);
101                             }
102                         }
103                     }
104                 }    
105                 result += result_local / float(scene->mLights[l]->GetNumberOfRays());
106             }
107             
108             // get texture coordinates
109             for (unsigned int i=0; i < getTextureCount(); i++)
110             {
111                 // get texture color
112                 const Vec4f& tex = getTexture(i)->GetTexel(ray.hit->GetUV(ray));
113 
114                 // combine texture color with the computed result
115                 result = result * tex.xyz();
116             }
117             /********************* normal PhongShader procedure end *********************/
118                 
119             /**
120              * get reflected ray
121              */
122                 Vec3f color_reflect;
123                 if (reflection > 0.0)
124                 {
125                     Ray reflect;
126                     reflect.org = hitpoint;
127                     reflect.dir = ray.dir - 2.0 * Dot(normal, ray.dir) * normal;
128                     Normalize(reflect.dir);
129                     
130                     color_reflect = scene->RayTrace(reflect);   
131                 }
132             
133             /**
134              * get refracted ray
135              */
136                 Vec3f color_refrac;
137                 if (transparency > 0.0)
138                 {
139                     /**
140                      * Snell's Law
141                      * compute incoming angle and refracted angle
142                      */
143                         // incoming angle
144                         float alpha = Dot( normal, -ray.dir );
145                         
146                         float discriminant = 1 - powf(refraction_temp,2.0) * (1 - alpha * alpha);
147                         if (discriminant < 0.0)
148                         {
149                             result += reflection * color_reflect;
150                             return result;
151                         }
152 
153                         // refracted angle
154                         float beta = sqrt(discriminant);
155                         
156                     /**
157                      * Fresnel Term
158                      */
159                         // compute reflection coefficient: s-polarised and p-polarised
160                         float refl_s =  powf( sin(alpha - beta) / sin(alpha + beta), 2.0 );
161                         float refl_p =  powf( tan(alpha - beta) / tan(alpha + beta), 2.0 );
162                         
163                         float R = 0.5 * (refl_s + refl_p);
164                         float T = 1.0 - R;
165                         
166                         result += (R * reflection) * color_reflect;
167                         
168                     /**
169                      * compute refracted ray
170                      */
171                         Ray refract;
172                         refract.org = hitpoint;
173                         refract.dir = refraction_temp * ray.dir + (refraction_temp * alpha - beta) * normal;
174                         
175                         Vec3f color_refract = scene->RayTrace(refract);
176                         
177                         result += (T * transparency) * color_refract;
178                 }
179             
180             return result;
181         };
182 };
183 
184 #endif


syntax highlighted by Code2HTML, v. 0.9.1