gKit2 light

- Main Page
- Related Pages
- Modules
- Classes
- Files

- File List
- File Members

ray_tuto3.cpp
1
2 #include <cstdio>
3 #include <cstdlib>
4 #include <cmath>
5 #include <cfloat>
6
7 #include "vec.h"
8 #include "mat.h"
9 #include "image.h"
10 #include "image_io.h"
11 #include "orbiter.h"
12 #include "ray.h"
13
15 struct Material
16 {
17 Color diffuse;
18 Color specular;
19 float ir;
20 float ns;
21 float kd;
22 float ks;
23 bool reflect;
24 bool refract;
25
26 Material( ) : diffuse(make_white()), specular(make_black()), ir(1.f), ns(0.f), kd(1.f), ks(0.f), reflect(false), refract(false) {}
27 };
28
29 Material make_diffuse( const Color& color )
30 {
31 Material m;
32 m.diffuse= color;
33 m.kd= 1;
34 m.ks= 0;
35 return m;
36 }
37
38 Material make_mirror( const Color& color, const float ir )
39 {
40 Material m;
41 m.diffuse= make_color(1, 1, 1);
42 m.specular= color;
43 m.kd= 0;
44 m.ks= 1;
45 m.ir= ir;
46 m.reflect= true;
47 m.reflect= false;
48 return m;
49 }
50
51 Material make_glass( const Color& color, const float ir )
52 {
53 Material m;
54 m.diffuse= make_color(1, 0, 1);
55 m.specular= color;
56 m.kd= 0;
57 m.ks= 1;
58 m.ir= ir;
59 m.reflect= true;
60 m.refract= true;
61 return m;
62 }
63
64
66 struct Sphere
67 {
68 Material material;
69 Transform model;
70 Point center;
71 float radius;
72
73 Sphere( const Point& c, const float r, const Color& cc ) : material(make_diffuse(cc)), model(make_identity()), center(c), radius(r) {}
74 Sphere( const Point& c, const float r, const Material& m ) : material(m), model(make_identity()), center(c), radius(r) {}
75 };
76
78 bool intersect( const Sphere& sphere, const Ray& ray, float& hit )
79 {
80 Point center= transform(sphere.model, sphere.center);
81 Vector oc= ray.origin - center;
82 float b= dot(oc, ray.direction);
83 float c= dot(oc, oc) - sphere.radius*sphere.radius;
84 // float d= dot(ray.direction, ray.direction) == 1, ray.direction == 1
85 float h= b*b - c;
86 if(h < 0.0) return false;
87
88 h= sqrt(h);
89 float t1= (-b - h);
90
91 /* solution classique avec les 2 racines :
92 */
93 float t2= (-b + h);
94 if(t1 <= 0 && t2 <= 0)
95 return false;
96
97 else if(t1 > 0 && t2 > 0)
98 t1= std::min(t1, t2); // plus petite racine postive
99 else
100 t1= std::max(t1, t2); // racine positive
101
102 // intersection valide ?
103 if(t1 < hit)
104 {
105 hit= t1;
106 return true;
107 }
108 else
109 return false;
110
111 /* solution courte : si l'origine du rayon est a l'exterieur de la sphere...
112 if(t1 < 0)
113 return false;
114 else if(t1 < hit)
115 {
116 hit= t1;
117 return true;
118 }
119 else
120 return false;
121 */
122 }
123
125 struct Plane
126 {
127 Material material;
128 Point anchor;
129 Vector normal;
130
131 Plane( const Point& a, const Vector& n, const Color& c= make_white() ) : material(make_diffuse(c)), anchor(a), normal(n) {}
132 Plane( const Point& a, const Vector& n, const Material& m ) : material(m), anchor(a), normal(n) {}
133 };
134
136 bool intersect( const Plane& plane, const Ray& ray, float &hit )
137 {
138 float t= dot(plane.anchor - ray.origin, plane.normal) / dot(ray.direction, plane.normal);
139 if(t < 0) return false;
140 if(t < hit)
141 {
142 hit= t;
143 return true;
144 }
145 else
146 return false;
147 }
148
149
151 std::vector<Plane> planes;
152 std::vector<Sphere> spheres;
153
155 bool intersect( const Ray& ray, const float tmax, Hit& hit, Material& m )
156 {
157 hit.hit= false;
158 float t= tmax;
159 for(unsigned int i= 0; i < (unsigned int) planes.size(); i++)
160 if(intersect(planes[i], ray, t))
161 {
162 hit.t= t;
163 hit.p= ray.origin + t * ray.direction;
164 hit.n= planes[i].normal;
165 hit.color= planes[i].material.diffuse;
166 hit.hit= true;
167
168 // damier
169 Vector p= make_vector(planes[i].anchor, hit.p);
170 int x= std::abs(std::floor(p.x));
171 int y= std::abs(std::floor(p.y));
172 int z= std::abs(std::floor(p.z));
173 Color color= ((x%2) ^ (z%2)) ? planes[i].material.diffuse : make_white();
174 hit.color= color;
175 m= make_diffuse(color);
176 //~ m= make_mirror(color, 1.f);
177 }
178
179 for(unsigned int i= 0; i < (unsigned int) spheres.size(); i++)
180 if(intersect(spheres[i], ray, t))
181 {
182 hit.t= t;
183 hit.p= ray.origin + t * ray.direction;
184 hit.n= normalize(make_vector(transform(spheres[i].model, spheres[i].center), hit.p));
185 m= spheres[i].material;
186 hit.hit= true;
187 }
188
189 return (t < tmax);
190 }
191
192 float shadow( const Point& p, const Vector& n, const Point& l )
193 {
194 Ray ray= make_ray(p + .001f * n, l);
195 Hit hit;
196 Material m;
197 intersect(ray, distance(p + .001f * n, l), hit, m);
198
199 return hit.hit ? 0.f : 1.f; // s'il y a une intersection p et q ne se voient pas...
200 }
201
202
203 int main( int argc, char **argv )
204 {
205 srand48(0);
206
207 // creer quelques objets
208 planes.push_back( Plane(make_point(0, 0, 0), normalize(make_vector(0, 1, 0)), make_red()) );
209 planes.push_back( Plane(make_point(0, 0, 16), normalize(make_vector(0, 0, -1)), make_red()) );
210 planes.push_back( Plane(make_point(0, 0, -16), normalize(make_vector(0, 0, 1)), make_white()) );
211
212 spheres.push_back( Sphere(make_point(0, 0, 0), 1, make_white()) );
213 //~ spheres.push_back( Sphere(make_point(0, 0, 0), 1, make_mirror(make_white(), 1.5f)) );
214 spheres.push_back( Sphere(make_point(1, 0, 0), 0.5f, make_red()) );
215 spheres.push_back( Sphere(make_point(0, 1, 0), 0.5f, make_green()) );
216 spheres.push_back( Sphere(make_point(0, 0, 1), 0.5f, make_blue()) );
217
218 // et quelques spheres miroir placees aleatoirement
219 for(int i= 0; i < 10; i++)
220 {
221 float x= drand48() * 20 - 10;
222 float y= drand48() * 5 + 2;
223 float z= drand48() * 20 - 10;
224 float r= drand48() * 2 + .25f;
225 spheres.push_back( Sphere(make_point(x, y, z), r, make_glass(make_white(), 1.3f)) );
226 }
227
228 // et une source de lumiere
229 Point light= make_point(10, 20, -2);
230 Color emission= make_white() * 500;
231
232 // reculer la camera pour observer les objets
233 Orbiter camera= make_orbiter_lookat( make_point(0, 0, 0), 15 );
234 orbiter_rotation(camera, 0, 45);
235
236 // go
237 Image image(1024, 640);
238
239 Point d0;
240 Vector dx, dy;
241 Point o= orbiter_position(camera);
242 orbiter_image_frame(camera, image.width(), image.height(), 0, 45, d0, dx, dy);
243
244 #pragma omp parallel for schedule(dynamic, 16)
245 for(int y= 0; y < image.height(); y++)
246 for(int x= 0; x < image.width(); x++)
247 {
248 Color pixel= make_black();
249
250 const int samples= 16;
251 for(int s= 0; s < samples; s++)
252 {
253 Point e= d0 + ((float) x + drand48() - 0.5f) * dx + ((float) y + drand48() - 0.5f) * dy;
254 Ray ray= make_ray(o, e);
255
256 Hit hit;
257 Material m;
258 if(intersect(ray, FLT_MAX, hit, m))
259 {
260 Color color= make_black();
261
262 if(m.reflect)
263 {
264 Ray mray= reflect(ray, hit.p, hit.n);
265 Hit mhit;
266 Material mm;
267 if(intersect(mray, FLT_MAX, mhit, mm))
268 {
269 // reflexion miroir
270 float cos_theta= std::max( 0.f, dot(normalize(make_vector(mhit.p, light)), mhit.n));
271 color= color + m.specular * fresnel(ray, hit.p, hit.n, m.ir) * emission / distance2(mhit.p, light) * mm.diffuse * shadow(mhit.p, mhit.n, light) * cos_theta;
272 }
273 else
274 color= color + m.specular * fresnel(ray, hit.p, hit.n, m.ir) * make_color(1, 1, 0) *2;
275 }
276
277 if(m.refract)
278 {
279 // entree dans l'objet
280 if(fresnel_refract(ray, hit.p, hit.n, m.ir))
281 {
282 Ray iray= refract(ray, hit.p, hit.n, m.ir);
283 Hit ihit;
284 Material im;
285 if(intersect(iray, FLT_MAX, ihit, im))
286 {
287 // sortie de l'objet
288 if(fresnel_refract(iray, ihit.p, ihit.n, im.ir))
289 {
290 Ray oray= refract(iray, ihit.p, ihit.n, im.ir);
291 Hit ohit;
292 Material om;
293 if(intersect(oray, FLT_MAX, ohit, om))
294 {
295 // transparence
296 float cos_theta= std::max( 0.f, dot(normalize(make_vector(ohit.p, light)), ohit.n));
297 color= color + m.specular * (1.f - fresnel(ray, hit.p, hit.n, m.ir)) * im.specular * (1.f - fresnel(iray, ihit.p, ihit.n, im.ir))
298 * emission / distance2(ohit.p, light) * om.diffuse * shadow(ohit.p, ohit.n, light) * cos_theta;
299 }
300 }
301 }
302 }
303 }
304
305 else
306 {
307 // diffus
308 float cos_theta= std::max( 0.f, dot(normalize(make_vector(hit.p, light)), hit.n));
309 color= emission / distance2(hit.p, light) * m.diffuse * shadow(hit.p, hit.n, light) * cos_theta;
310 }
311
312 pixel= pixel + color;
313 }
314 }
315
316 image(x, y)= Color(pixel / (float) samples, 1);
317 }
318
319 write_image(image, "render.png");
320 return 0;
321 }
Orbiter
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet...
Definition: orbiter.h:16
Hit::p
Point p
position
Definition: ray.h:37
normalize
Vector normalize(const Vector &v)
renvoie un vecteur unitaire / longueur == 1.
Definition: vec.cpp:79
Material::kd
float kd
ks * diffuse + ks * speculaire, kd + ks == 1
Definition: ray_tuto3.cpp:21
Material::reflect
bool reflect
specualr reflect
Definition: ray_tuto3.cpp:23
Color
representation d'une couleur (rgba) transparente ou opaque.
Definition: color.h:13
Hit::color
Color color
couleur de la surface au point d'intersection
Definition: ray.h:39
image.h
Material
representation d'une matiere
Definition: ray_tuto3.cpp:15
Vector
representation d'un vecteur 3d.
Definition: vec.h:42
mat.h
dot
float dot(const Vector &u, const Vector &v)
renvoie le produit scalaire de 2 vecteurs.
Definition: vec.cpp:93
Hit::t
float t
abscisse : p= o + t.d
Definition: ray.h:40
Hit
representation d'un point d'intersection.
Definition: ray.h:33
Hit::n
Vector n
normale de la surface au point d'intersection
Definition: ray.h:38
Material::refract
bool refract
specualr refract
Definition: ray_tuto3.cpp:24
Transform
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:20
write_image
int write_image(const Image &image, const char *filename)
enregistre une image dans un fichier png.
Definition: image_io.cpp:88
Ray
representation d'un rayon.
Definition: ray.h:12
Image
representation d'une image.
Definition: image.h:18
distance
float distance(const Point &a, const Point &b)
renvoie la distance etre 2 points.
Definition: vec.cpp:7
Point
representation d'un point 3d.
Definition: vec.h:19
image_io.h
Material::ns
float ns
exposant blinn phong
Definition: ray_tuto3.cpp:20
center
Point center(const Point &a, const Point &b)
renvoie le milieu du segment ab.
Definition: vec.cpp:17
orbiter.h
Sphere
representation d'une sphere.
Definition: ray_tuto3.cpp:66
Material::ir
float ir
indice de refraction
Definition: ray_tuto3.cpp:19
distance2
float distance2(const Point &a, const Point &b)
renvoie le carre de la distance etre 2 points.
Definition: vec.cpp:12
vec.h
Plane
representation d'un plan. point + normale.
Definition: ray_tuto3.cpp:125