97 Shape *nearest_shape = top->nearest_intersection(origin_shape, ray, nearest_distance); |
97 Shape *nearest_shape = top->nearest_intersection(origin_shape, ray, nearest_distance); |
98 |
98 |
99 if (nearest_shape == NULL) { |
99 if (nearest_shape == NULL) { |
100 return bg_colour; |
100 return bg_colour; |
101 } else { |
101 } else { |
102 Colour acc = Colour(); |
102 Colour col = Colour(); |
103 Vector3 P = ray.o + ray.dir * nearest_distance; // point of intersection |
103 Vector3 P = ray.o + ray.dir * nearest_distance; // point of intersection |
104 Vector3 normal = nearest_shape->normal(P); |
104 Vector3 normal = nearest_shape->normal(P); |
|
105 bool from_inside = false; |
|
106 |
105 // make shapes double sided |
107 // make shapes double sided |
106 if (dot(normal, ray.dir) > 0.0) |
108 if (dot(normal, ray.dir) > 0.0) |
|
109 { |
107 normal = - normal; |
110 normal = - normal; |
108 acc = PhongShader_ambient(*nearest_shape->material, P); |
111 from_inside = true; |
|
112 } |
|
113 |
|
114 col = PhongShader_ambient(*nearest_shape->material, P); |
109 |
115 |
110 vector<Light*>::iterator light; |
116 vector<Light*>::iterator light; |
111 for (light = lights.begin(); light != lights.end(); light++) { |
117 for (light = lights.begin(); light != lights.end(); light++) { |
112 Vector3 jo, L = (*light)->pos - P; // direction vector to light |
118 Vector3 jo, L = (*light)->pos - P; // direction vector to light |
113 L.normalize(); |
119 L.normalize(); |
121 continue; |
127 continue; |
122 } |
128 } |
123 |
129 |
124 // shading function |
130 // shading function |
125 Vector3 R = L - 2.0 * L_dot_N * normal; |
131 Vector3 R = L - 2.0 * L_dot_N * normal; |
126 acc += PhongShader_calculate(*nearest_shape->material, |
132 col += PhongShader_calculate(*nearest_shape->material, |
127 P, normal, R, ray.dir, **light); |
133 P, normal, R, ray.dir, **light); |
128 } |
134 } |
129 } |
135 } |
130 |
136 |
131 // reflection |
137 if (depth < max_depth) |
132 Vector3 newdir = ray.dir - 2.0 * dot(ray.dir, normal) * normal; |
138 { |
133 if (depth < max_depth && nearest_shape->material->reflection > 0.01) { |
139 Colour trans_col, refl_col; |
134 Ray newray = Ray(P, newdir); |
140 Float trans = nearest_shape->material->transmissivity; |
135 Colour refl_col = raytrace(newray, depth + 1, nearest_shape); |
141 Float refl = nearest_shape->material->reflectivity; |
136 acc += nearest_shape->material->reflection * refl_col; |
142 const Float cos_i = - dot(normal, ray.dir); |
137 } |
143 |
138 |
144 // reflection |
139 // refraction |
145 if (refl > 0.01) |
140 /* ... */ |
146 { |
|
147 Vector3 newdir = ray.dir + 2.0 * cos_i * normal; |
|
148 Ray newray = Ray(P, newdir); |
|
149 refl_col = raytrace(newray, depth + 1, nearest_shape); |
|
150 } |
|
151 |
|
152 // refraction |
|
153 if (trans > 0.01) |
|
154 { |
|
155 Float n, n1, n2; |
|
156 if (from_inside) |
|
157 { |
|
158 n1 = nearest_shape->material->refract_index; |
|
159 n2 = 1.0; |
|
160 n = n1; |
|
161 } |
|
162 else |
|
163 { |
|
164 n1 = 1.0; |
|
165 n2 = nearest_shape->material->refract_index; |
|
166 n = 1.0 / n2; |
|
167 } |
|
168 const Float sin2_t = n*n * (1 - cos_i*cos_i); |
|
169 if (sin2_t >= 1.0) |
|
170 { |
|
171 // totally reflected |
|
172 refl += trans; |
|
173 trans = 0; |
|
174 } |
|
175 else |
|
176 { |
|
177 const Float cos_t = sqrtf(1 - sin2_t); |
|
178 const Float Rdiv = 1.0/(n1*cos_i + n2*cos_t); |
|
179 const Float Rper = (n1*cos_i - n2*cos_t)*Rdiv; |
|
180 const Float Rpar = (n2*cos_i - n1*cos_t)*Rdiv; |
|
181 const Float R = (Rper*Rper + Rpar*Rpar)/2; |
|
182 refl += R*trans; |
|
183 trans = (1-R)*trans; |
|
184 Vector3 newdir = n * ray.dir + (n*cos_i - cos_t) * normal; |
|
185 Ray newray = Ray(P, newdir); |
|
186 trans_col = raytrace(newray, depth + 1, nearest_shape); |
|
187 } |
|
188 } |
|
189 col = (1-refl-trans)*col + refl*refl_col + trans*trans_col; |
|
190 } |
141 |
191 |
142 // ambient occlusion |
192 // ambient occlusion |
143 if (ao_samples) |
193 if (ao_samples) |
144 { |
194 { |
145 Float miss = 0; |
195 Float miss = 0; |