commit 3f6ca06228f94f44afa590569fbdfc61a2962558 Author: MrDev023 Date: Thu Oct 20 21:16:34 2016 +0200 Init diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9eef680 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +CPP_FILES := $(wildcard src/*.cpp) +OBJ_FILES := $(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o))) +LD_FLAGS := +CC_FLAGS := -std=gnu++11 + +ifeq ($(OS),Windows_NT) +EXEC := main.exe +else +EXEC := main +endif + +$(EXEC): $(OBJ_FILES) + g++ $(LD_FLAGS) -o $@ $^ + +obj/%.o: src/%.cpp + mkdir -p obj + g++ $(CC_FLAGS) -c -o $@ $< + +clean: + rm obj/* + rm $(EXEC) diff --git a/main b/main new file mode 100755 index 0000000..d665e19 Binary files /dev/null and b/main differ diff --git a/obj/main.o b/obj/main.o new file mode 100644 index 0000000..27b8fe6 Binary files /dev/null and b/obj/main.o differ diff --git a/scene.txt b/scene.txt new file mode 100644 index 0000000..9ba30a8 --- /dev/null +++ b/scene.txt @@ -0,0 +1,10 @@ +640 480 +3 3 2 +1.0 1.0 0.0 0.5 +0.0 1.0 1.0 0.5 +1.0 0.0 1.0 0.5 +233.0 290.0 0.0 100 0 +407.0 290.0 0.0 100 1 +320.0 140.0 0.0 100 2 +0.0 240.0 -100.0 1.0 1.0 1.0 +640.0 240.0 -10000.0 0.6 0.7 1.0 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..6e487a3 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include +using namespace std; + +#include "raytracer.h" + + bool init(char* inputName, scene &myScene) + { + int nbMat, nbSphere, nbLight; + int i; + ifstream sceneFile(inputName); + if (!sceneFile) + return false; + sceneFile >> myScene.sizex >> myScene.sizey; + sceneFile >> nbMat >> nbSphere >> nbLight; + myScene.matTab.resize(nbMat); + myScene.sphTab.resize(nbSphere); + myScene.lgtTab.resize(nbLight); + for (i=0; i < nbMat; i++) + sceneFile >> myScene.matTab[i]; + for (i=0; i < nbSphere; i++) + sceneFile >> myScene.sphTab[i]; + for (i=0; i < nbLight; i++) + sceneFile >> myScene.lgtTab[i]; + return true; + } + + bool hitSphere(const ray &r, const sphere &s, float &t) + { + // intersection rayon/sphere + vecteur dist = s.pos - r.start; + float B = r.dir * dist; + float D = B*B - dist * dist + s.size * s.size; + if (D < 0.0f) + return false; + float t0 = B - sqrtf(D); + float t1 = B + sqrtf(D); + bool retvalue = false; + if ((t0 > 0.1f) && (t0 < t)) + { + t = t0; + retvalue = true; + } + if ((t1 > 0.1f) && (t1 < t)) + { + t = t1; + retvalue = true; + } + return retvalue; + } + + bool draw(char* outputName, scene &myScene) + { + ofstream imageFile(outputName,ios_base::binary); + if (!imageFile) + return false; + // Ajout du header TGA + imageFile.put(0).put(0); + imageFile.put(2); /* RGB non compresse */ + + imageFile.put(0).put(0); + imageFile.put(0).put(0); + imageFile.put(0); + + imageFile.put(0).put(0); /* origine X */ + imageFile.put(0).put(0); /* origine Y */ + + imageFile.put((myScene.sizex & 0x00FF)).put((myScene.sizex & 0xFF00) / 256); + imageFile.put((myScene.sizey & 0x00FF)).put((myScene.sizey & 0xFF00) / 256); + imageFile.put(24); /* 24 bit bitmap */ + imageFile.put(0); + // fin du header TGA + + // balayage + for (int y = 0; y < myScene.sizey; ++y) { + for (int x = 0; x < myScene.sizex; ++x) { + float red = 0, green = 0, blue = 0; + float coef = 1.0f; + int level = 0; + // lancer de rayon + ray viewRay = { {float(x), float(y), -10000.0f}, { 0.0f, 0.0f, 1.0f}}; + do + { + // recherche de l'intersection la plus proche + float t = 20000.0f; + int currentSphere= -1; + + for (unsigned int i = 0; i < myScene.sphTab.size(); ++i) + { + if (hitSphere(viewRay, myScene.sphTab[i], t)) + { + currentSphere = i; + } + } + + if (currentSphere == -1) + break; + + point newStart = viewRay.start + t * viewRay.dir; + // la normale au point d'intersection + vecteur n = newStart - myScene.sphTab[currentSphere].pos; + float temp = n * n; + if (temp == 0.0f) + break; + + temp = 1.0f / sqrtf(temp); + n = temp * n; + + material currentMat = myScene.matTab[myScene.sphTab[currentSphere].material]; + + // calcul de la valeur d'éclairement au point + for (unsigned int j = 0; j < myScene.lgtTab.size(); ++j) { + light current = myScene.lgtTab[j]; + vecteur dist = current.pos - newStart; + if (n * dist <= 0.0f) + continue; + float t = sqrtf(dist * dist); + if ( t <= 0.0f ) + continue; + ray lightRay; + lightRay.start = newStart; + lightRay.dir = (1/t) * dist; + // calcul des ombres + bool inShadow = false; + for (unsigned int i = 0; i < myScene.sphTab.size(); ++i) { + if (hitSphere(lightRay, myScene.sphTab[i], t)) { + inShadow = true; + break; + } + } + if (!inShadow) { + // lambert + float lambert = (lightRay.dir * n) * coef; + red += lambert * current.red * currentMat.red; + green += lambert * current.green * currentMat.green; + blue += lambert * current.blue * currentMat.blue; + } + } + + // on itére sur la prochaine reflexion + coef *= currentMat.reflection; + float reflet = 2.0f * (viewRay.dir * n); + viewRay.start = newStart; + viewRay.dir = viewRay.dir - reflet * n; + + level++; + } + while ((coef > 0.0f) && (level < 10)); + + imageFile.put((unsigned char)min(blue*255.0f,255.0f)).put((unsigned char)min(green*255.0f, 255.0f)).put((unsigned char)min(red*255.0f, 255.0f)); + } + } + return true; + } + + int main(int argc, char* argv[]) { + scene myScene; + if (!init("scene.txt", myScene)) + return -1; + if (!draw("test.tga", myScene)) + return -1; + return 0; + } \ No newline at end of file diff --git a/src/raytracer.h b/src/raytracer.h new file mode 100644 index 0000000..c8ff91d --- /dev/null +++ b/src/raytracer.h @@ -0,0 +1,83 @@ + + +struct point { + float x, y, z; +}; + +istream & operator >> ( istream &inputFile, point& p ) { + return inputFile >> p.x >> p.y >> p.z ; +} + +struct vecteur { + float x, y, z; +}; + +istream & operator >> ( istream &inputFile, vecteur& v ) { + return inputFile >> v.x >> v.y >> v.z ; +} + +point operator + (const point&p, const vecteur &v){ + point p2={p.x + v.x, p.y + v.y, p.z + v.z }; + return p2; +} + +point operator - (const point&p, const vecteur &v){ + point p2={p.x - v.x, p.y - v.y, p.z - v.z }; + return p2; +} + +vecteur operator - (const point&p1, const point &p2){ + vecteur v={p1.x - p2.x, p1.y - p2.y, p1.z - p2.z }; + return v; +} + +vecteur operator * (float c, const vecteur &v) +{ + vecteur v2={v.x *c, v.y * c, v.z * c }; + return v2; +} + +vecteur operator - (const vecteur&v1, const vecteur &v2){ + vecteur v={v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; + return v; +} + +float operator * (const vecteur&v1, const vecteur &v2 ) { + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; +} + +struct material { + float red, green, blue, reflection; +}; +istream & operator >> ( istream &inputFile, material& mat ) { + return inputFile >> mat.red >> mat.green >> mat.blue >> mat.reflection; +} + +struct sphere { + point pos; + float size; + int material; +}; +istream & operator >> ( istream &inputFile, sphere& sph ) { + return inputFile >> sph.pos >> sph.size >> sph.material; +} + +struct light { + point pos; + float red, green, blue; +}; +istream & operator >> ( istream &inputFile, light& lig ) { + return inputFile >> lig.pos >> lig.red >> lig.green >> lig.blue; +} + +struct ray { + point start; + vecteur dir; +}; + +struct scene { + vector matTab; + vector sphTab; + vector lgtTab; + int sizex, sizey; +}; \ No newline at end of file diff --git a/test.tga b/test.tga new file mode 100644 index 0000000..5ad6463 Binary files /dev/null and b/test.tga differ