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