1
0
Fork 0
This commit is contained in:
MrDev023 2016-10-20 21:16:34 +02:00
commit 3f6ca06228
7 changed files with 281 additions and 0 deletions

21
Makefile Normal file
View file

@ -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)

BIN
main Executable file

Binary file not shown.

BIN
obj/main.o Normal file

Binary file not shown.

10
scene.txt Normal file
View file

@ -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

167
src/main.cpp Normal file
View file

@ -0,0 +1,167 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <limits>
#include <algorithm>
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;
}

83
src/raytracer.h Normal file
View file

@ -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<material> matTab;
vector<sphere> sphTab;
vector<light> lgtTab;
int sizex, sizey;
};

BIN
test.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB