From: gburri Date: Thu, 15 Jan 2015 17:17:50 +0000 (+0100) Subject: Implémentation du raytracing pour Global Memory/Shared Memory/Constant Memory X-Git-Url: https://git.euphorik.ch/?a=commitdiff_plain;h=f8259dce248a4411c3bc64cecb9fc268c4fd81d6;p=GPU.git Implémentation du raytracing pour Global Memory/Shared Memory/Constant Memory --- diff --git a/WCudaMSE/BilatTools_CPP/src/core/tools/cpp/AleaTools.cpp b/WCudaMSE/BilatTools_CPP/src/core/tools/cpp/AleaTools.cpp index f55adc1..38912a6 100755 --- a/WCudaMSE/BilatTools_CPP/src/core/tools/cpp/AleaTools.cpp +++ b/WCudaMSE/BilatTools_CPP/src/core/tools/cpp/AleaTools.cpp @@ -21,6 +21,11 @@ AleaTools::AleaTools() srand(time(NULL)); } +AleaTools::AleaTools(uint seed) + { + srand(seed); + } + AleaTools::~AleaTools() { // rien diff --git a/WCudaMSE/BilatTools_CPP/src/core/tools/cpp/namespace_cpu/IndiceTools_CPU.cpp b/WCudaMSE/BilatTools_CPP/src/core/tools/cpp/namespace_cpu/IndiceTools_CPU.cpp index b70c829..efc02fe 100755 --- a/WCudaMSE/BilatTools_CPP/src/core/tools/cpp/namespace_cpu/IndiceTools_CPU.cpp +++ b/WCudaMSE/BilatTools_CPP/src/core/tools/cpp/namespace_cpu/IndiceTools_CPU.cpp @@ -20,12 +20,19 @@ namespace cpu *ptrJ = s - w * (*ptrI); } + float2 IndiceTools::toPixelFloat(int s, int w) + { + const float y = (float)s / (float)w; + const float x = (float)s - (float)w * y; + return { x, y }; + } + /** * i[0,H[ j[0,W[ --> s[0,W*H[ */ - int IndiceTools::toS(int W, int i, int j) + int IndiceTools::toS(int w, int i, int j) { - return (i * W) + j; + return (i * w) + j; } } diff --git a/WCudaMSE/BilatTools_CPP/src/core/tools/header/AleaTools.h b/WCudaMSE/BilatTools_CPP/src/core/tools/header/AleaTools.h index 4420132..287e015 100755 --- a/WCudaMSE/BilatTools_CPP/src/core/tools/header/AleaTools.h +++ b/WCudaMSE/BilatTools_CPP/src/core/tools/header/AleaTools.h @@ -25,6 +25,8 @@ class AleaTools */ AleaTools(); + AleaTools(uint seed); + /*--------------------------------------*\ |* Destructor *| \*-------------------------------------*/ diff --git a/WCudaMSE/BilatTools_CPP/src/core/tools/header/namespace_cpu/IndiceTools_CPU.h b/WCudaMSE/BilatTools_CPP/src/core/tools/header/namespace_cpu/IndiceTools_CPU.h index a97f64b..1c3027e 100755 --- a/WCudaMSE/BilatTools_CPP/src/core/tools/header/namespace_cpu/IndiceTools_CPU.h +++ b/WCudaMSE/BilatTools_CPP/src/core/tools/header/namespace_cpu/IndiceTools_CPU.h @@ -1,6 +1,8 @@ #ifndef INDICE_TOOLS_CPU_H_ #define INDICE_TOOLS_CPU_H_ +#include "cudaType_CPU.h" + /*----------------------------------------------------------------------*\ |* Declaration *| \*---------------------------------------------------------------------*/ @@ -29,12 +31,17 @@ namespace cpu /** * s[0,W*H[ --> i[0,H[ j[0,W[ */ - static void toIJ(int s, int W, int* ptri, int* ptrj); + static void toIJ(int s, int w, int* ptri, int* ptrj); + + /** + * s[0,W*H[ --> x[0,W[ y[0,H[ + */ + static float2 toPixelFloat(int s, int w); /** * i[0,H[ j[0,W[ --> s[0,W*H[ */ - static int toS(int W, int i, int j); + static int toS(int w, int i, int j); /*-------------------------------------*\ |* Attributs *| diff --git a/WCudaMSE/BilatTools_Cuda/src/core/cudatools/header/device/IndiceTools_GPU.h b/WCudaMSE/BilatTools_Cuda/src/core/cudatools/header/device/IndiceTools_GPU.h index d230aef..f62ddf3 100755 --- a/WCudaMSE/BilatTools_Cuda/src/core/cudatools/header/device/IndiceTools_GPU.h +++ b/WCudaMSE/BilatTools_Cuda/src/core/cudatools/header/device/IndiceTools_GPU.h @@ -2,6 +2,7 @@ #define INDICES_TOOLS_GPU_H_ #include "both_define.h" +#include "cudaType_CPU.h" /*----------------------------------------------------------------------*\ |* Declaration *| @@ -34,12 +35,24 @@ namespace gpu * h = hauteur */ __BOTH__ - static void toIJ( int s, int w, int* ptrI, int* ptrJ) + static void toIJ( int s, int w, int* ptrI, int* ptrJ) { *ptrI = s / w; *ptrJ = s - w * (*ptrI); } + /** + * s[0,W*H[ --> x[0,W[ y[0,H[ + */ + __BOTH__ + static float2 toPixelFloat(int s, int w) + { + const int y = s / w; + const int x = s - w * y; + const float2 pixel = { (float)x, (float)y }; + return pixel; + } + /** * i[0,H[ j[0,W[ --> s[0,W*H[ * w = largeur @@ -60,7 +73,7 @@ namespace gpu }; } -#endif +#endif /*----------------------------------------------------------------------*\ |* End *| diff --git a/WCudaMSE/BilatTools_Cuda/src/core/cudatools/header/host/cudaTools.h b/WCudaMSE/BilatTools_Cuda/src/core/cudatools/header/host/cudaTools.h index 8c0834d..5b48c74 100755 --- a/WCudaMSE/BilatTools_Cuda/src/core/cudatools/header/host/cudaTools.h +++ b/WCudaMSE/BilatTools_Cuda/src/core/cudatools/header/host/cudaTools.h @@ -10,12 +10,11 @@ // cublas #include "cublas_v2.h" // Pour specifier la version qu'on veut! (definition CUBLASAPI) //#include "cublas.h" // Pour specifier la version qu'on veut!(definition CUBLASAPI) -#include "cublas_api.h" // Après include "cublas_v2.h" ou "cublas.h" +#include "cublas_api.h" // Apr�s include "cublas_v2.h" ou "cublas.h" - - - -typedef unsigned char uchar; +#ifndef uchar + typedef unsigned char uchar; +#endif /*----------------------------------------------------------------------*\ |* Declaration *| diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/RayTracingCommon.h b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/RayTracingCommon.h new file mode 100644 index 0000000..0f2d3ae --- /dev/null +++ b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/RayTracingCommon.h @@ -0,0 +1,13 @@ +#ifndef RAY_TRACING_COMMON +#define RAY_TRACING_COMMON + +#define NB_SPHERES 2000 + + +#define MEMORY_MODEL_GLOBAL 1 +#define MEMORY_MODEL_CONSTANT 2 +#define MEMORY_MODEL_SHARED 3 + +#define CURRENT_MEMORY_MODEL MEMORY_MODEL_SHARED + +#endif diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/RayTracingDevice.cu b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/RayTracingDevice.cu index 3d80bc4..97fc839 100644 --- a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/RayTracingDevice.cu +++ b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/RayTracingDevice.cu @@ -1,39 +1,106 @@ #include -#include +#include +#include using namespace std; +#include "Indice1D.h" #include "Indice2D.h" #include "IndiceTools.h" +#include "ColorTools.h" #include "cudaTools.h" #include "Device.h" #include "RayTracingDevice.h" -__global__ -void rayTracing(uchar4* ptrDevPixels, int w, int h, float t) +#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT +// Les spheres dans la constant memory. +__constant__ Sphere CONST_SPHERES[NB_SPHERES]; + +ConstantMemoryLink constantMemorySpheresLink() + { + float* ptrDevTabData; + size_t sizeAll = NB_SPHERES * sizeof(Sphere); + HANDLE_ERROR(cudaGetSymbolAddress((void**)&ptrDevTabData, CONST_SPHERES)); + ConstantMemoryLink cmLink = + { + (void**)ptrDevTabData, NB_SPHERES, sizeAll + }; + return cmLink; + } +#endif + +#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL or CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED + __global__ + void rayTracing(uchar4* ptrDevPixels, const Sphere* ptrDevSpheres, int w, int h, float t) +#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT + __global__ + void rayTracing(uchar4* ptrDevPixels, int w, int h, float t) +#endif { + const int TID = Indice2D::tid(); const int NB_THREAD = Indice2D::nbThread(); const int WH = w * h; - uchar4 color; - color.w = 255; // Par défaut, l'image est opaque. +#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED + __shared__ Sphere tabSpheresSM[NB_SPHERES]; - double x, y; - int pixelI, pixelJ; + // Copy the global memory to shared memory. + const int NB_THREAD_LOCAL = Indice1D::nbThreadBlock(); + const int TID_LOCAL = Indice1D::tidLocal(); + int sLocal = TID_LOCAL; + while (sLocal < NB_SPHERES) + { + tabSpheresSM[sLocal] = ptrDevSpheres[sLocal]; + sLocal += NB_THREAD_LOCAL; + } + + __syncthreads(); +#endif int s = TID; while (s < WH) { - IndiceTools::toIJ(s, w, &pixelI, &pixelJ); // update (pixelI, pixelJ) + const float2 pixel = IndiceTools::toPixelFloat(s, w); + + // Les données de la sphère sélectionnée. + float selectedSphereDistance = FLT_MAX; + float brightness = 0; + float hue = 0; + + // Sélectionne la sphere la plus proche, il peut ne pas y avoir de sphère. + for (int i = 0; i < NB_SPHERES; ++i) + { +#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL + const Sphere& sphere = ptrDevSpheres[i]; +#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT + const Sphere& sphere = CONST_SPHERES[i]; +#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED + const Sphere& sphere = tabSpheresSM[i]; +#endif + const float hSquare = sphere.hSquare(pixel); + + if (sphere.isBelow(hSquare)) + { + const float dz = sphere.dz(hSquare); + const float sphereDistance = sphere.distance(dz); - // (i,j) domaine écran. - // (x,y) domaine math. - // domaineMath.toXY(pixelI, pixelJ, &x, &y); // (i,j) -> (x,y). + if (sphereDistance < selectedSphereDistance) + { + selectedSphereDistance = sphereDistance; + brightness = sphere.brightness(dz); + hue = sphere.hue(t); + } + } + } - // newtonMath.colorXY(&color, x, y); + // Si une sphere a pu être trouvée. + if (selectedSphereDistance != FLT_MAX) + { + ColorTools::HSB_TO_RVB(hue, 1, brightness, &ptrDevPixels[s]); + } - ptrDevPixels[s] = color; + ptrDevPixels[s].w = 255; s += NB_THREAD; } diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/RayTracingDevice.h b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/RayTracingDevice.h index 1500c43..350ba9c 100644 --- a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/RayTracingDevice.h +++ b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/RayTracingDevice.h @@ -1,7 +1,26 @@ #ifndef RAY_TRACING_DEVICE_H #define RAY_TRACING_DEVICE_H -__global__ -void rayTracing(uchar4* ptrDevPixels, int w, int h, float t); +#include "ConstantMemoryLink.h" + +#include "Sphere.h" +#include "RayTracingCommon.h" + +#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL or CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED + + __global__ + void rayTracing(uchar4* ptrDevPixels, const Sphere* ptrDevSpheres, int w, int h, float t); + +#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT + + /** + * Accès à la mémoire constante contenant les sphères. + */ + ConstantMemoryLink constantMemorySpheresLink(); + + __global__ + void rayTracing(uchar4* ptrDevPixels, int w, int h, float t); + +#endif #endif diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/Sphere.h b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/Sphere.h index a437dab..3c8df6e 100644 --- a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/Sphere.h +++ b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/Sphere.h @@ -7,19 +7,28 @@ class Sphere { public: - __host__ + /*__host__ Sphere(float3 centre, float r, float hue) : centre(centre), hueInitial(hue) { this->setR(r); - } + }*/ __host__ + __device__ Sphere() { } + /*Sphere(const Sphere& other) : + r(other.r), + centre(other.centre), + rCarre(other.rCarre), + T(other.T) + { + }*/ + __host__ void setCentre(const float3& centre) { @@ -30,64 +39,74 @@ class Sphere void setR(float r) { this->r = r; - this->rCarre = r*r; + this->rCarre = r * r; } __host__ void setHueInitial(float hue) { - this->hueInitial = hue; + this->T = asinf(2 * hue - 1) - 3 * PI / 2; } + /* + * Calcul de h². + */ __device__ - float hCarre(float2 xySol) + float hSquare(float2 xySol) const { - float a = (centre.x - xySol.x); - float b = (centre.y - xySol.y); + const float a = (this->centre.x - xySol.x); + const float b = (this->centre.y - xySol.y); return a * a + b * b; } + /* + * Est-ce que la sphre se trouve en dessous d'un point (x, y) en fonction de h². + * Voir la méthode 'hCarre(..)'. + */ __device__ - bool isEnDessous(float hCarre) + bool isBelow(float hCarre) const { - return hCarre < rCarre; + return hCarre < this->rCarre; } + /* + * Hauteur du point de collision du rayon par rapport au centre de la sphère. + */ __device__ - float dz(float hCarre) + float dz(float hCarre) const { return sqrtf(rCarre - hCarre); } __device__ - float brightness(float dz) + float distance(float dz) const { - return dz / r; + return this->centre.z - dz; } + /** + * Renvoie la le B de HSB compris entre 0 et 1. + */ __device__ - float distance(float dz) + float brightness(float dz) const { - return centre.z - dz; + return dz / this->r; } + /* + * La couleur + */ __device__ - float getHueInitial() + float hue(float t) const { - return this->hueInitial; - } - - __device__ - float hue(float t) // usefull for animation - { - return 0.5 + 0.5 * sin(t + T + 3 * PI / 2); + return 0.5 + 0.5 * sinf(t + this->T + 3 * PI / 2); } private: - float r; - float3 centre; - float hueInitial; - float rCarre; + float r; // Rayon. + float3 centre; // Position. + + float rCarre; // Précalul de r². float T; // Utilisé pour l'animation. }; diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/host/RayTracing.cu b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/host/RayTracing.cu index 1623820..8742692 100644 --- a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/host/RayTracing.cu +++ b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/host/RayTracing.cu @@ -9,19 +9,39 @@ using namespace std; #include "Device.h" #include "RayTracingDevice.h" #include "Sphere.h" - -RayTracing::RayTracing(int w, int h) - : w(w), h(h), - dg(8, 8, 1), - db(32, 32, 1), - title("Ray Tracing") +#include "RayTracingCommon.h" + +RayTracing::RayTracing(int w, int h) : + t(0), w(w), h(h), + dg(8, 8, 1), + db(32, 32, 1), + alea(42), +#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL + title("Ray Tracing (Global memory)") +#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT + title("Ray Tracing (Constant memory)") +#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED + title("Ray Tracing (Shared memory)") +#endif { Device::assertDim(dg, db); - const int nbSpheres = 10; - Sphere* shperes = this->createSpheres(10); - - // Copie les spheres dans la constant memory. + Sphere* spheres = this->createSpheres(NB_SPHERES); + +#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL or CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED + // Copie des spheres dans la global memory. + const size_t sizeSpheres = NB_SPHERES * sizeof(Sphere); + HANDLE_ERROR(cudaMalloc(&this->ptrDevSpheres, sizeSpheres)); + HANDLE_ERROR(cudaMemcpy(this->ptrDevSpheres, spheres, sizeSpheres, cudaMemcpyHostToDevice)); +#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT + // Copie des spheres en constant memory. + ConstantMemoryLink cmSpheresLink = constantMemorySpheresLink(); + Sphere* ptrDevConstSperes = (Sphere*)cmSpheresLink.ptrDevTab; + size_t sizeALL = cmSpheresLink.sizeAll; + HANDLE_ERROR(cudaMemcpy(ptrDevConstSperes, spheres, sizeALL, cudaMemcpyHostToDevice)); +#endif + + cout << "sizeof(Sphere): " << sizeof(Sphere) << endl; } RayTracing::~RayTracing() @@ -30,14 +50,18 @@ RayTracing::~RayTracing() void RayTracing::runGPU(uchar4* ptrDevPixels) { +#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL or CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED + rayTracing<<>>(ptrDevPixels, this->ptrDevSpheres, this->w, this->h, this->t); +#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT rayTracing<<>>(ptrDevPixels, this->w, this->h, this->t); +#endif - // HANDLE_ERROR(cudaDeviceSynchronize()); // Pour flusher les 'printf' (pour le DEBUG). + HANDLE_ERROR(cudaDeviceSynchronize()); // Pour flusher les 'printf' (pour le DEBUG). } void RayTracing::animationStep() { - this->t += 0.1; // TODO. + this->t += 0.005; } int RayTracing::getW() @@ -63,20 +87,25 @@ string RayTracing::getTitle() Sphere* RayTracing::createSpheres(int n) { Sphere* spheres = new Sphere[n]; - const float bord = 200; + const int RAYON_MIN = 10; + const int RAYON_MAX = this->w / 10 - 1; + + const float bord = RAYON_MAX + 1; for (int i = 0; i < n; ++i) { - spheres[i].setR(float(this->alea.uniformeAB(20, this->w / 10 - 1))); + spheres[i].setR(float(this->alea.uniformeAB(RAYON_MIN, RAYON_MAX))); - float3 centre + const float3 centre = { - float(this->alea.uniformeAB(double(bord), double(this->w - bord))), - float(this->alea.uniformeAB(double(bord), double(this->h - bord))), - float(this->alea.uniformeAB(10.0, 2.0 * this->w)) + float(this->alea.uniformeAB(double(bord), double(this->w - bord))), // x. + float(this->alea.uniformeAB(double(bord), double(this->h - bord))), // y. + float(this->alea.uniformeAB(10.0, 2.0 * this->w)) // z. }; spheres[i].setCentre(centre); spheres[i].setHueInitial(float(this->alea.uniformeAB(0.0, 1.0))); } + + return spheres; } diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/host/RayTracing.h b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/host/RayTracing.h index 313fa6b..1f9536d 100644 --- a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/host/RayTracing.h +++ b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/host/RayTracing.h @@ -25,8 +25,13 @@ class RayTracing : public Animable_I std::string getTitle(void) /*override*/; private: + /** + * Crée un tablean de 'n' sphères dont le rayon, la couleur et la position sont générés aléatoirement. + */ Sphere* createSpheres(int n); + Sphere* ptrDevSpheres; // Pointeur sur la mémoire du GPU. + AleaTools alea; float t; diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/provider/RayTracingProvider.cpp b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/provider/RayTracingProvider.cpp index f232f0b..2d82571 100644 --- a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/provider/RayTracingProvider.cpp +++ b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/provider/RayTracingProvider.cpp @@ -10,6 +10,6 @@ RayTracing* RayTracingProvider::create() Image* RayTracingProvider::createGL() { - ColorRGB_01* ptrColorTitre = new ColorRGB_01(0, 0, 0); + ColorRGB_01* ptrColorTitre = new ColorRGB_01(255, 255, 255); return new Image(create(), ptrColorTitre); // both ptr destroy by destructor of ImageFonctionel } diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/mainGL.cpp b/WCudaMSE/Student_Cuda_Image/src/cpp/core/mainGL.cpp index d7a9fec..13dd2db 100755 --- a/WCudaMSE/Student_Cuda_Image/src/cpp/core/mainGL.cpp +++ b/WCudaMSE/Student_Cuda_Image/src/cpp/core/mainGL.cpp @@ -20,7 +20,7 @@ using namespace std; int mainGL(const vector& args) { - const string defaultCommand = "demo"; + const string defaultCommand = "raytracing"; const string command = args.size() > 0 ? args[0] : defaultCommand; // AutoViewer rippling0(true, true, 10, 10); // Warmup. @@ -40,6 +40,8 @@ int mainGL(const vector& args) AutoViewer newtown(true, true, 10, 10); else if (command == "heat-transfert") AutoViewer heatTransfert(true, false, 10, 10); + else if (command == "raytracing") + AutoViewer rayTracing(true, true, 20, 20); else if (command == "convolution") { const string videoPath = args.size() >= 2 ? args[1] : "/media/Data/Video/nasaFHD_short.avi"; // Vidéo par défaut si pas donnée en paramètre. @@ -60,7 +62,5 @@ int mainGL(const vector& args) cout << "Command unknown: " << command << endl; } - // AutoViewer rayTracing(true, true, 20, 20); // Commenté car projet approfondit. - return EXIT_SUCCESS; }