gKit2 light
Loading...
Searching...
No Matches
tuto_bvh2_gltf_brdf.cpp File Reference

bvh 2 niveaux et instances, charge un fichier gltf... + utilitaires... More...

#include <random>
#include <algorithm>
#include <vector>
#include <cfloat>
#include "vec.h"
#include "mat.h"
#include "color.h"
#include "image.h"
#include "image_io.h"
#include "orbiter.h"
#include "gltf.h"

Go to the source code of this file.

Classes

struct  Ray
 rayon. More...
struct  Hit
 intersection avec un triangle. More...
struct  BBoxHit
 intersection avec une boite / un englobant. More...
struct  BBox
 boite englobante. More...
struct  Node
 construction de l'arbre / BVH. More...
struct  BVHT< T >
 bvh parametre par le type des primitives, cf triangle et instance... More...
struct  Triangle
 triangle pour le bvh, cf fonction bounds() et intersect(). More...
struct  Instance
 instance pour le bvh, cf fonctions bounds() et intersect(). More...
struct  Brdf
 regroupe tous les parametres de la matiere du point d'intersection. More...
struct  Sampler
 generation de nombres aleatoires entre 0 et 1. More...

Typedefs

typedef BVHT< TriangleBVH
typedef BVHT< TriangleBLAS
typedef BVHT< InstanceTLAS

Functions

Node make_node (const BBox &bounds, const int left, const int right)
 creation d'un noeud interne.
Node make_leaf (const BBox &bounds, const int begin, const int end)
 creation d'une feuille.
Point hit_position (const Hit &hit, const Ray &ray)
 renvoie la position du point d'intersection sur le rayon.
bool has_normals (const Hit &hit, const GLTFScene &scene)
 verifie la presence des normales par sommet.
Vector hit_normal (const Hit &hit, const GLTFScene &scene)
 renvoie la normale interpolee au point d'intersection dans le repere de la scene.
Vector triangle_normal (const Hit &hit, const GLTFScene &scene)
 normale geometrique du triangle, si necessaire... ie si has_normals(hit, scene) == false...
bool has_texcoords (const Hit &hit, const GLTFScene &scene)
 verifie la presence des coordonnees de texture...
vec2 hit_texcoords (const Hit &hit, const GLTFScene &scene)
 renvoie les coordonnees de texture du point d'intersection, suppose que has_texcoords(hit, scene) == true
Color sample_texture (const vec2 &t, const ImageData &texture)
const GLTFMaterialhit_material (const Hit &hit, const GLTFScene &scene)
 renvoie la matiere du point d'intersection.
Color hit_color (const Hit &hit, const GLTFScene &scene)
 renvoie la couleur de base de la matiere du point d'intersection.
Brdf hit_brdf (const Hit &hit, const GLTFScene &scene, const std::vector< ImageData > &textures)
 evalue les parametres pbr (couleur, metal, rugosite) de la matiere au point d'intersection, en fonction des textures aussi, si necessaire
int main (int argc, char **argv)

Detailed Description

bvh 2 niveaux et instances, charge un fichier gltf... + utilitaires...

Definition in file tuto_bvh2_gltf_brdf.cpp.


Class Documentation

◆ Brdf

struct Brdf

regroupe tous les parametres de la matiere du point d'intersection.

Definition at line 534 of file tuto_bvh2_gltf_brdf.cpp.

Class Members
Vector n normale interpolee du point d'intersection
Color diffuse color.
Color F0 fresnel.
Color emission emission pour les sources de lumieres ou pas (= noir).
float metallic metallic / dielectrique.
float alpha rugosite de la micro surface.
float transmission transmission, transparent ou pas (= 0)

Typedef Documentation

◆ BVH

typedef BVHT<Triangle> BVH

Definition at line 306 of file tuto_bvh2_gltf_brdf.cpp.

◆ BLAS

typedef BVHT<Triangle> BLAS

Definition at line 307 of file tuto_bvh2_gltf_brdf.cpp.

◆ TLAS

typedef BVHT<Instance> TLAS

Definition at line 361 of file tuto_bvh2_gltf_brdf.cpp.

Function Documentation

◆ make_node()

Node make_node ( const BBox & bounds,
const int left,
const int right )

creation d'un noeud interne.

Definition at line 114 of file tuto_bvh2_gltf_brdf.cpp.

115{
116 Node node { bounds, left, right };
117 assert(node.internal()); // verifie que c'est bien un noeud...
118 return node;
119}
void bounds(const MeshData &data, Point &pmin, Point &pmax)
renvoie l'englobant.
construction de l'arbre / BVH.
Definition tuto_bvh.cpp:133

◆ make_leaf()

Node make_leaf ( const BBox & bounds,
const int begin,
const int end )

creation d'une feuille.

Definition at line 122 of file tuto_bvh2_gltf_brdf.cpp.

123{
124 Node node { bounds, -begin, -end };
125 assert(node.leaf()); // verifie que c'est bien une feuille...
126 return node;
127}
void begin(Widgets &w)
debut de la description des elements de l'interface graphique.
Definition widgets.cpp:29

◆ hit_position()

Point hit_position ( const Hit & hit,
const Ray & ray )

renvoie la position du point d'intersection sur le rayon.

Definition at line 365 of file tuto_bvh2_gltf_brdf.cpp.

365{ assert(hit.triangle_id != -1); return ray.o + hit.t * ray.d; }

◆ has_normals()

bool has_normals ( const Hit & hit,
const GLTFScene & scene )

verifie la presence des normales par sommet.

Definition at line 368 of file tuto_bvh2_gltf_brdf.cpp.

369{
370 assert(hit.mesh_id != -1);
371 assert(hit.primitive_id != -1);
372 const GLTFMesh& mesh= scene.meshes[hit.mesh_id];
373 const GLTFPrimitives& primitives= mesh.primitives[hit.primitive_id];
374 return primitives.normals.size() > 0;
375}
description d'un maillage.
Definition gltf.h:115
groupe de triangles d'un maillage. chaque groupe est associe a une matiere.
Definition gltf.h:99

◆ hit_normal()

Vector hit_normal ( const Hit & hit,
const GLTFScene & scene )

renvoie la normale interpolee au point d'intersection dans le repere de la scene.

Definition at line 378 of file tuto_bvh2_gltf_brdf.cpp.

379{
380 assert(hit.instance_id != -1);
381 assert(hit.mesh_id != -1);
382 assert(hit.primitive_id != -1);
383 assert(hit.triangle_id != -1);
384 const GLTFMesh& mesh= scene.meshes[hit.mesh_id];
385 const GLTFPrimitives& primitives= mesh.primitives[hit.primitive_id];
386
387 // indice des sommets
388 int a= primitives.indices[3*hit.triangle_id];
389 int b= primitives.indices[3*hit.triangle_id+1];
390 int c= primitives.indices[3*hit.triangle_id+2];
391
392 // normales des sommets
393 assert(primitives.normals.size());
394 Vector na= primitives.normals[a];
395 Vector nb= primitives.normals[b];
396 Vector nc= primitives.normals[c];
397
398 // interpole la normale au point d'intersection
399 // attention : il faut utiliser la meme convetion barycentrique que la fonction d'intersection rayon/triangle !!
400 Vector n= (1 - hit.u - hit.v) * na + hit.u * nb + hit.v * nc;
401
402 // transforme la normale dans le repere de la scene
403 const GLTFNode& node= scene.nodes[hit.instance_id];
404 // les normales ne se transforment pas exactement comme les positions...
405 // les sommets sont transformes par node.model, comment transformer la normale pour quelle reste perpendiculaire au triangle ? cf Transform::normal()
406 Transform T= node.model.normal();
407
408 n= normalize( T(n) );
409 return n;
410}
Transform model
transformation model pour dessiner le maillage.
Definition gltf.h:130
position et orientation d'un maillage dans la scene.
Definition gltf.h:129
Vector normalize(const Vector &v)
renvoie un vecteur unitaire / longueur == 1.
Definition vec.cpp:167
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition mat.h:21
Transform normal() const
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m.
Definition mat.cpp:181
representation d'un vecteur 3d.
Definition vec.h:67

◆ triangle_normal()

Vector triangle_normal ( const Hit & hit,
const GLTFScene & scene )

normale geometrique du triangle, si necessaire... ie si has_normals(hit, scene) == false...

Definition at line 413 of file tuto_bvh2_gltf_brdf.cpp.

414{
415 assert(hit.instance_id != -1);
416 assert(hit.mesh_id != -1);
417 assert(hit.primitive_id != -1);
418 assert(hit.triangle_id != -1);
419 const GLTFMesh& mesh= scene.meshes[hit.mesh_id];
420 const GLTFPrimitives& primitives= mesh.primitives[hit.primitive_id];
421
422 // indice des sommets
423 int a= primitives.indices[3*hit.triangle_id];
424 int b= primitives.indices[3*hit.triangle_id+1];
425 int c= primitives.indices[3*hit.triangle_id+2];
426
427 // postion des sommets
428 assert(primitives.positions.size());
429 Point pa= primitives.positions[a];
430 Point pb= primitives.positions[b];
431 Point pc= primitives.positions[c];
432
433 // normale geometrique
434 Vector n= cross( Vector(pa, pb), Vector(pa, pc) );
435
436 // transforme la normale dans le repere de la scene
437 const GLTFNode& node= scene.nodes[hit.instance_id];
438 // les normales ne se transforment pas exactement comme les positions...
439 // les sommets sont transformes par node.model, comment transformer la normale pour quelle reste perpendiculaire au triangle ? cf Transform::normal()
440 Transform T= node.model.normal();
441
442 n= normalize( T(n) );
443 return n;
444}
Vector cross(const Vector &u, const Vector &v)
renvoie le produit vectoriel de 2 vecteurs.
Definition vec.cpp:173
representation d'un point 3d.
Definition vec.h:21

◆ has_texcoords()

bool has_texcoords ( const Hit & hit,
const GLTFScene & scene )

verifie la presence des coordonnees de texture...

Definition at line 447 of file tuto_bvh2_gltf_brdf.cpp.

448{
449 assert(hit.mesh_id != -1);
450 assert(hit.primitive_id != -1);
451 const GLTFMesh& mesh= scene.meshes[hit.mesh_id];
452 const GLTFPrimitives& primitives= mesh.primitives[hit.primitive_id];
453 return primitives.texcoords.size() > 0;
454}

◆ hit_texcoords()

vec2 hit_texcoords ( const Hit & hit,
const GLTFScene & scene )

renvoie les coordonnees de texture du point d'intersection, suppose que has_texcoords(hit, scene) == true

Definition at line 457 of file tuto_bvh2_gltf_brdf.cpp.

458{
459 assert(hit.instance_id != -1);
460 assert(hit.mesh_id != -1);
461 assert(hit.primitive_id != -1);
462 assert(hit.triangle_id != -1);
463 const GLTFMesh& mesh= scene.meshes[hit.mesh_id];
464 const GLTFPrimitives& primitives= mesh.primitives[hit.primitive_id];
465
466 // indice des sommets
467 int a= primitives.indices[3*hit.triangle_id];
468 int b= primitives.indices[3*hit.triangle_id+1];
469 int c= primitives.indices[3*hit.triangle_id+2];
470
471 // texcoords des sommets
472 assert(primitives.texcoords.size());
473 vec2 ta= primitives.texcoords[a];
474 vec2 tb= primitives.texcoords[b];
475 vec2 tc= primitives.texcoords[c];
476
477 // interpole au point d'intersection
478 // attention : il faut utiliser la meme convention barycentrique que la fonction d'intersection rayon/triangle !!
479 vec2 t= vec2( (1 - hit.u - hit.v) * ta.x + hit.u * tb.x + hit.v * tc.x, (1 - hit.u - hit.v) * ta.y + hit.u * tb.y + hit.v * tc.y );
480 return t;
481}
vecteur generique, utilitaire.
Definition vec.h:152

◆ sample_texture()

Color sample_texture ( const vec2 & t,
const ImageData & texture )

renvoie la couleur d'un pixel d'une texture/image chargee par read_gltf_images() todo : interpolation bilineaire des texels autour de t...

Definition at line 486 of file tuto_bvh2_gltf_brdf.cpp.

487{
488 // retrouve les coordonnes de t dans l'image
489 int tx= int(t.x * texture.width) % texture.width;
490 int ty= int(t.y * texture.height) % texture.height;
491 // attention aux repetitions, les coordoornees ne sont pas toujours entre 0 et 1 !!
492 if(tx < 0) tx= -tx;
493 if(ty < 0) ty= -ty;
494
495 // respecte la convention gltf, origine en haut de l'image...
496 ty= texture.height - 1 - ty;
497 // position du pixel dans l'image
498 size_t offset= texture.offset(tx, ty);
499
500 // recupere la couleur du pixel
501 Color color= Color(texture.pixels[offset], texture.pixels[offset+1], texture.pixels[offset+2], 255) / 255;
502 if(texture.channels > 3)
503 // alpha / transparence, si disponible
504 color.a= float(texture.pixels[offset+3]) / float(255);
505
506 return color;
507}
representation d'une couleur (rgba) transparente ou opaque.
Definition color.h:14

◆ hit_material()

const GLTFMaterial & hit_material ( const Hit & hit,
const GLTFScene & scene )

renvoie la matiere du point d'intersection.

Definition at line 513 of file tuto_bvh2_gltf_brdf.cpp.

514{
515 assert(hit.mesh_id != -1);
516 assert(hit.primitive_id != -1);
517 const GLTFMesh& mesh= scene.meshes[hit.mesh_id];
518 const GLTFPrimitives& primitives= mesh.primitives[hit.primitive_id];
519 if(primitives.material_index == -1)
520 return default_material;
521
522 assert(primitives.material_index < int(scene.materials.size()));
523 return scene.materials[primitives.material_index];
524}
int material_index
indice de la matiere des primitives.
Definition gltf.h:102

◆ hit_color()

Color hit_color ( const Hit & hit,
const GLTFScene & scene )

renvoie la couleur de base de la matiere du point d'intersection.

Definition at line 527 of file tuto_bvh2_gltf_brdf.cpp.

528{
529 return hit_material(hit, scene).color;
530}
Color color
base color.
Definition gltf.h:60
const GLTFMaterial & hit_material(const Hit &hit, const GLTFScene &scene)
renvoie la matiere du point d'intersection.

◆ hit_brdf()

Brdf hit_brdf ( const Hit & hit,
const GLTFScene & scene,
const std::vector< ImageData > & textures )

evalue les parametres pbr (couleur, metal, rugosite) de la matiere au point d'intersection, en fonction des textures aussi, si necessaire

Definition at line 548 of file tuto_bvh2_gltf_brdf.cpp.

549{
550 // recupere la description de la matiere...
551 const GLTFMaterial& material= hit_material(hit, scene);
552
553 // et les coordonnees de textures, si elles existent...
554 vec2 texcoords= vec2(.5, .5);
555 bool use_texture= has_texcoords(hit, scene) && textures.size();
556 if(use_texture)
557 texcoords= hit_texcoords(hit, scene);
558
559 Color color= material.color;
560 if(use_texture && material.color_texture != -1 && material.color_texture < int(textures.size()))
561 color= color * sample_texture(texcoords, textures[material.color_texture]);
562
563 float metallic= material.metallic;
564 float roughness= material.roughness;
565 if(use_texture && material.metallic_roughness_texture != -1 && material.metallic_roughness_texture < int(textures.size()))
566 {
567 Color texel= sample_texture(texcoords, textures[material.metallic_roughness_texture]);
568 metallic= metallic * texel.b;
569 roughness= roughness * texel.g;
570 }
571
572 float transmission= material.transmission;
573 if(use_texture && material.transmission_texture != -1 && material.transmission_texture < int(textures.size()))
574 transmission= transmission * sample_texture(texcoords, textures[material.transmission_texture]).r;
575
576 Brdf brdf;
577 {
578 if(has_normals(hit, scene))
579 // normale interpolee
580 brdf.n= hit_normal(hit, scene);
581 else
582 // normale geometrique du triangle
583 brdf.n= triangle_normal(hit, scene);
584
585 brdf.diffuse= (1 - metallic) * color;
586 brdf.F0= (1 - metallic) * Color(0.04) + metallic * color;
587 // todo utiliser material.ior a la place de 0.04, si metal==0 et ior != 0
588 // todo utiliser material.specular a la place de F0, si metal==0 et specular != black
589 brdf.emission= material.emission;
590 brdf.metallic= metallic;
591 brdf.alpha= roughness * roughness;
592 brdf.transmission= transmission;
593 }
594
595 return brdf;
596}
float transmission
transmission, transparent ou pas (= 0)
Definition gltf.h:64
int color_texture
indice de la texture ou -1. cf read_gltf_images() pour charger les textures dans le bon ordre....
Definition gltf.h:73
float roughness
rugosite de la micro surface.
Definition gltf.h:63
int metallic_roughness_texture
indice de la texture ou -1. les valeurs RGB representent les parametres du modele : B= metallic,...
Definition gltf.h:74
Color emission
emission pour les sources de lumieres ou pas (= noir).
Definition gltf.h:61
int transmission_texture
indice de la texture ou -1.
Definition gltf.h:78
float metallic
metallic / dielectrique.
Definition gltf.h:62
Vector triangle_normal(const Hit &hit, const GLTFScene &scene)
normale geometrique du triangle, si necessaire... ie si has_normals(hit, scene) == false....
Color emission
emission pour les sources de lumieres ou pas (= noir).
float alpha
rugosite de la micro surface.
Vector hit_normal(const Hit &hit, const GLTFScene &scene)
renvoie la normale interpolee au point d'intersection dans le repere de la scene.
Color sample_texture(const vec2 &t, const ImageData &texture)
float transmission
transmission, transparent ou pas (= 0)
Color diffuse
color.
bool has_normals(const Hit &hit, const GLTFScene &scene)
verifie la presence des normales par sommet.
bool has_texcoords(const Hit &hit, const GLTFScene &scene)
verifie la presence des coordonnees de texture...
vec2 hit_texcoords(const Hit &hit, const GLTFScene &scene)
renvoie les coordonnees de texture du point d'intersection, suppose que has_texcoords(hit,...
Vector n
normale interpolee du point d'intersection
float metallic
metallic / dielectrique.
Color F0
fresnel.
regroupe tous les parametres de la matiere du point d'intersection.

◆ main()

int main ( int argc,
char ** argv )

Definition at line 614 of file tuto_bvh2_gltf_brdf.cpp.

615{
616 const char *mesh_filename= "data/robot.gltf";
617 const char *orbiter_filename= nullptr;
618
619 if(argc > 1) mesh_filename= argv[1];
620 if(argc > 2) orbiter_filename= argv[2];
621
622 GLTFScene scene= read_gltf_scene(mesh_filename);
623
624 // construit les bvh des objets de la scene, en parallele ! cf BLAS / bvh de triangles
625 std::vector<BVH *> bvhs(scene.meshes.size());
626 {
627 // parcourir les mesh
628 printf("%d meshes\n", int(scene.meshes.size()));
629
630 #pragma omp parallel for
631 for(unsigned mesh_id= 0; mesh_id < scene.meshes.size(); mesh_id++)
632 {
633 const GLTFMesh& mesh= scene.meshes[mesh_id];
634
635 // groupes de triangles du mesh
636 std::vector<Triangle> triangles;
637 for(unsigned primitive_id= 0; primitive_id < mesh.primitives.size(); primitive_id++)
638 {
639 const GLTFPrimitives& primitives= mesh.primitives[primitive_id];
640
641 for(unsigned i= 0; i +2 < primitives.indices.size(); i+= 3)
642 {
643 // extraire les positions des sommets du triangle
644 vec3 a= primitives.positions[primitives.indices[i]];
645 vec3 b= primitives.positions[primitives.indices[i+1]];
646 vec3 c= primitives.positions[primitives.indices[i+2]];
647 triangles.push_back( Triangle(a, b, c, mesh_id, primitive_id, i/3) );
648 // stocke aussi l'indice du triangle
649 }
650 }
651
652 BVH *bvh= new BVH;
653 bvh->build(triangles);
654 bvhs[mesh_id]= bvh;
655 }
656 }
657
658 // instancie les objets de la scene, cf TLAS / bvh d'instances
659 TLAS top_bvh;
660 {
661 printf("%d nodes\n", int(scene.nodes.size()));
662
663 // 1 instance par noeud de la scene gltf
664 std::vector<Instance> instances;
665 for(unsigned node_id= 0; node_id < scene.nodes.size(); node_id++)
666 {
667 const GLTFNode& node= scene.nodes[node_id];
668 const GLTFMesh& mesh= scene.meshes[node.mesh_index];
669
670 instances.push_back( Instance( BBox(mesh.pmin, mesh.pmax), node.model, bvhs[node.mesh_index], node_id ) );
671 }
672
673 top_bvh.build(instances);
674 printf("done. %d instances\n", int(instances.size()));
675 }
676
677 // charge les textures...
678 std::vector<ImageData> textures= read_gltf_images(mesh_filename);
679
680
681 // recupere les matrices de la camera gltf
682 assert(scene.cameras.size());
683 Transform view= scene.cameras[0].view;
684 Transform projection= scene.cameras[0].projection;
685
686 // cree l'image en respectant les proportions largeur/hauteur de la camera gltf
687 int width= 1024;
688 int height= width / scene.cameras[0].aspect;
689 Image image(width, height, Color(0.2));
690
691 // transformations
692 Transform model= Identity();
693 Transform viewport= Viewport(image.width(), image.height());
694 Transform inv= Inverse(viewport * projection * view * model);
695
696
697 // calcule l'image en parallele avec openMP
698#pragma omp parallel for
699 for(unsigned y= 0; y < image.height(); y++)
700 for(unsigned x= 0; x < image.width(); x++)
701 {
702 // genere le rayon pour le pixel x,y
703 Point o= inv( Point(x, y, 0) ); // origine
704 Point e= inv( Point(x, y, 1) ); // extremite
705 Ray ray(o, Vector(o, e));
706
707 // intersections !
708 if(Hit hit= top_bvh.intersect(ray))
709 {
710 // evalue les parametres de la matiere au point d'intersection
711 Brdf fr= hit_brdf(hit, scene, textures);
712
713 float cos_theta= std::abs(dot(fr.n, normalize(ray.d)));
714 Color color= fr.diffuse * cos_theta;
715
716 image(x, y)= Color(color, 1);
717 }
718 }
719 printf("\n");
720
721 write_image(image, "render.png");
722 return 0;
723}
representation d'une image.
Definition image.h:21
int mesh_index
indice du maillage.
Definition gltf.h:131
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().
Definition text.cpp:140
bool write_image(const Image &image, const char *filename, const bool flipY)
enregistre une image au format .png
Definition image_io.cpp:225
Transform Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Definition mat.cpp:197
Transform Viewport(const float width, const float height)
renvoie la matrice representant une transformation viewport.
Definition mat.cpp:357
Transform Identity()
construit la transformation identite.
Definition mat.cpp:187
float dot(const Vector &u, const Vector &v)
renvoie le produit scalaire de 2 vecteurs.
Definition vec.cpp:181
boite englobante.
Definition tuto_bvh.cpp:47
intersection avec un triangle.
Definition tuto_bvh2.cpp:33
instance pour le bvh, cf fonctions bounds() et intersect().
rayon.
Definition tuto_bvh2.cpp:20
triangle pour le bvh, cf fonction bounds() et intersect().
Definition tuto_bvh.cpp:84
vecteur generique, utilitaire.
Definition vec.h:169
Brdf hit_brdf(const Hit &hit, const GLTFScene &scene, const std::vector< ImageData > &textures)
evalue les parametres pbr (couleur, metal, rugosite) de la matiere au point d'intersection,...