25#define EPSILON 0.00001f
34 Ray(
const Point origine,
const Point extremite ) : o(origine), d(Vector(origine, extremite)), tmax(1) {}
35 Ray(
const Point origine,
const Vector direction ) : o(origine), d(direction), tmax(FLT_MAX) {}
37 Point operator( ) (
const float t )
const {
return o + t * d; }
47 Hit( ) : p(), n(), t(FLT_MAX), u(0), v(0), object_id(-1) {}
52 Triangle( ) : TriangleData() {}
53 Triangle(
const TriangleData& data ) : TriangleData(data) {}
63 bool intersect(
const Ray &ray,
const float htmax,
float &rt,
float &ru,
float&rv )
const
66 Vector ac= Vector(Point(a), Point(
c));
67 Vector pvec=
cross(ray.d, ac);
70 Vector ab= Vector(Point(a), Point(b));
71 float det=
dot(ab, pvec);
72 if(det > -EPSILON && det < EPSILON)
75 float inv_det= 1.0f / det;
78 Vector tvec(Point(a), ray.o);
81 float u=
dot(tvec, pvec) * inv_det;
82 if(u < 0.0f || u > 1.0f)
86 Vector qvec=
cross(tvec, ab);
89 float v=
dot(ray.d, qvec) * inv_det;
90 if(v < 0.0f || u + v > 1.0f)
94 rt=
dot(ac, qvec) * inv_det;
99 return (rt < htmax && rt > EPSILON);
106 float w= 1.f - u - v;
114 float w= 1.f - u - v;
121struct Source :
public Triangle
125 Source( ) : Triangle(), emission() {}
126 Source(
const TriangleData& data,
const Color& color ) : Triangle(data), emission(color) {}
135 World(
const Vector& _n ) : n(_n)
137 if(n.z < -0.9999999f)
144 float a= 1.f / (1.f + n.z);
145 float d= -n.x * n.y * a;
146 t=
Vector(1.f - n.x * n.x * a, d, -n.x);
147 b=
Vector(d, 1.f - n.y * n.y * a, -n.y);
153 return local.x * t + local.y * b + local.z * n;
162GLuint
make_texture(
const int unit,
const int width,
const int height )
165 glGenTextures(1, &texture);
166 glActiveTexture(GL_TEXTURE0 + unit);
167 glBindTexture(GL_TEXTURE_2D, texture);
169 glTexImage2D(GL_TEXTURE_2D, 0,
170 GL_RGB32F, width, height, 0,
171 GL_RGBA, GL_FLOAT, NULL);
174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
175 glGenerateMipmap(GL_TEXTURE_2D);
183 IS(
const char *filename ) :
App(1024, 640)
186 if(m_mesh.vertex_count() == 0)
192 if(m_camera.read_orbiter(
"orbiter.txt") < 0)
195 m_mesh.bounds(pmin, pmax);
196 m_camera.lookat(pmin, pmax);
202 if(m_mesh.vertex_count() == 0)
213 glGenVertexArrays(1, &m_vao);
214 glBindVertexArray(m_vao);
220 glClearColor(0.2f, 0.2f, 0.2f, 1.f);
223 glDepthFunc(GL_LESS);
224 glEnable(GL_DEPTH_TEST);
231 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
236 reload_program(m_program,
"gkit2_tutos/M2/is.glsl");
244 m_mesh.bounds(pmin, pmax);
245 m_camera.lookat(pmin, pmax);
250 unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
251 if(mb & SDL_BUTTON(1))
252 m_camera.rotation(mx, my);
253 else if(mb & SDL_BUTTON(3))
255 else if(mb & SDL_BUTTON(2))
270 SDL_GetMouseState(&mx, &my);
272 texcoord=
vec2(pixel.x / m_hitp.width(), pixel.y / m_hitp.height());
273 printf(
"pixel %f %f\n", pixel.x, pixel.y);
278 m_camera.frame(0, d0, dx0, dy0);
282 m_camera.frame(1, d1, dx1, dy1);
285 Point o= d0 + pixel.x*dx0 + pixel.y*dy0;
286 Point e= d1 + pixel.x*dx1 + pixel.y*dy1;
293 if(intersect(ray, hit))
299 #pragma omp parallel for schedule(dynamic, 16)
300 for(
unsigned y= 0; y < m_hitp.height(); y++)
301 for(
unsigned x= 0; x < m_hitp.width(); x++)
304 m_hitp(x, y)=
Black();
305 m_hitn(x, y)=
Black();
306 m_hitv(x, y)=
Black();
308 Point o= d0 + x*dx0 + y*dy0;
309 Point e= d1 + x*dx1 + y*dy1;
313 if(intersect(ray, hit))
315 m_hitp(x, y)=
Color(hit.p.x, hit.p.y, hit.p.z);
316 m_hitn(x, y)=
Color(hit.n.x, hit.n.y, hit.n.z);
318 Ray shadow(hit.p + hit.n * 0.001f, point + normal * 0.001f);
321 if(intersect(shadow, shadow_hit))
324 m_hitv(x, y)=
Color(v, v, v);
329 glActiveTexture(GL_TEXTURE0);
330 glBindTexture(GL_TEXTURE_2D, m_ptexture);
331 glTexSubImage2D(GL_TEXTURE_2D, 0,
332 0, 0, m_hitp.width(), m_hitp.height(),
333 GL_RGBA, GL_FLOAT, m_hitp.data());
335 glActiveTexture(GL_TEXTURE0 +1);
336 glBindTexture(GL_TEXTURE_2D, m_ntexture);
337 glTexSubImage2D(GL_TEXTURE_2D, 0,
338 0, 0, m_hitn.width(), m_hitn.height(),
339 GL_RGBA, GL_FLOAT, m_hitn.data());
341 glActiveTexture(GL_TEXTURE0 +2);
342 glBindTexture(GL_TEXTURE_2D, m_vtexture);
343 glTexSubImage2D(GL_TEXTURE_2D, 0,
344 0, 0, m_hitv.width(), m_hitv.height(),
345 GL_RGBA, GL_FLOAT, m_hitv.data());
352 glBindVertexArray(m_vao);
353 glUseProgram(m_program);
355 program_uniform(m_program,
"ptexture", 0);
356 program_uniform(m_program,
"ntexture", 1);
357 program_uniform(m_program,
"vtexture", 2);
358 program_uniform(m_program,
"pixel", texcoord);
359 program_uniform(m_program,
"mode", mode);
361 glActiveTexture(GL_TEXTURE0);
362 glBindTexture(GL_TEXTURE_2D, m_ptexture);
363 glActiveTexture(GL_TEXTURE0 +1);
364 glBindTexture(GL_TEXTURE_2D, m_ntexture);
365 glActiveTexture(GL_TEXTURE0 +2);
366 glBindTexture(GL_TEXTURE_2D, m_vtexture);
368 glDrawArrays(GL_TRIANGLES, 0, 3);
372 draw(m_mesh, m_camera);
381 sprintf(tmp,
"screenshot%02d.png", n++);
382 printf(
"writing %s...\n", tmp);
409 printf(
"%d sources.\n", (
int) m_sources.size());
410 return (
int) m_sources.size();
413 bool direct(
const Ray& ray )
415 for(
size_t i= 0; i < m_sources.size(); i++)
418 if(m_sources[i].intersect(ray, ray.tmax, t, u, v))
427 int build_triangles( )
429 for(
int i= 0; i < m_mesh.triangle_count(); i++)
430 m_triangles.push_back( Triangle(m_mesh.triangle(i)) );
432 printf(
"%d triangles.\n", (
int) m_triangles.size());
433 return (
int) m_triangles.size();
438 bool intersect(
const Ray& ray, Hit& hit )
441 for(
size_t i= 0; i < m_triangles.size(); i++)
444 if(m_triangles[i].intersect(ray, hit.t, t, u, v))
451 hit.n= m_triangles[i].normal(u, v);
457 return (hit.object_id != -1);
464 std::vector<Triangle> m_triangles;
465 std::vector<Source> m_sources;
480int main(
int argc,
char **argv )
482 const char *filename=
"data/cornell.obj";
App(const int width, const int height, const int major=3, const int minor=3, const int samples=0)
constructeur, dimensions de la fenetre et version d'openGL.
representation d'une image.
Mesh & triangle(const unsigned int a, const unsigned int b, const unsigned int c)
int triangle_count() const
renvoie le nombre de triangles.
const Material & triangle_material(const unsigned int id) const
renvoie la matiere d'un triangle.
int window_height()
renvoie la hauteur de la fenetre de l'application.
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
int key_state(const SDL_Keycode key)
renvoie l'etat d'une touche du clavier. cf la doc SDL2 pour les codes.
int window_width()
renvoie la largeur de la fenetre de l'application.
Color Black()
utilitaire. renvoie une couleur noire.
float dot(const Vector &u, const Vector &v)
renvoie le produit scalaire de 2 vecteurs.
Vector cross(const Vector &u, const Vector &v)
renvoie le produit vectoriel de 2 vecteurs.
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
GLuint make_texture(const int unit, const int width, const int height, const GLenum texel_type, const GLenum data_format, const GLenum data_type)
creation de textures filtrables / mipmaps
int screenshot(const char *filename)
enregistre le contenu de la fenetre dans un fichier. doit etre de type .png / .bmp
GLuint read_program(const char *filename, const char *definitions)
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
representation d'une couleur (rgba) transparente ou opaque.
intersection avec un triangle.
int render()
a deriver pour afficher les objets. renvoie 1 pour continuer, 0 pour fermer l'application.
int init()
a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
int quit()
a deriver pour detruire les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
Color emission
pour une source de lumiere.
representation d'un point 3d.
representation d'un triangle.
triangle pour le bvh, cf fonction bounds() et intersect().
Point point(const float u, const float v) const
Vector normal(const float u, const float v) const
representation d'un vecteur 3d.
vecteur generique, utilitaire.