-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRay.cpp
More file actions
157 lines (139 loc) · 6.17 KB
/
Ray.cpp
File metadata and controls
157 lines (139 loc) · 6.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* \author Marie DARRIGOL & Anthony LEONARD & Ophélie PELLOUX-PRAYER & Olivier SOLDANO
* \project Ray-Tracing
* \file Ray.cpp
* \brief represent a ray casted from some position
*/
#include "Ray.h"
#include "SceneObject.h"
#include "Scene.h"
#include "Octree.h"
#include "collision.h"
#include <algorithm>
Ray::Ray(Vec3 pOrigin, Vec3 vDir, int ttl) : origin(pOrigin), direction(vDir), ttl(ttl) {}
/**
*\fn Color Ray::phong_ambiant(Material &mat, Light &light)
*\brief phong's ambiant reflection of this Ray, according to the Material of the collided SceneObject
* and its Lighting.
*\return a new Color giving the RGB color componants each range between 0.0f and 1.0f
*/
Color Ray::phong_ambiant(Material &mat, Scene & scene){
Color ambiant_color;
for (int i = 0; i < (int)scene.getLights()->size(); i++) {
ambiant_color = ambiant_color * (float) i + Color( mat.get_color() * (mat.get_phong_ambiant() *
scene.getLights()->at(i)->get_ambiant()));
}
ambiant_color.normalise();
return ambiant_color;
}
/**
*\fn float lambertian(Vec3 &collision_point, Vec3 &normal, Light &light)
*\brief express the lambertian coefficient describing the self shadowing due to the inclination
toward light of a point on a SceneObject
*\return a float representing this factor,
*/
float lambertian(Vec3 &collision_point, Vec3 &normal, Vec3 &light_direction) {
float lambert = normal * light_direction;
return (lambert > 0.0f) ? lambert : 0.0f;
}
/**
*\fn Color Ray::phong_diffuse(Vec3 &collision_point, Vec3 &norm, Material &mat, Light &light)
*\brief phong's diffuse reflection of this Ray, according to the normal vector of the collided SceneObject
* and its Material.
*\return a new Color giving the RGB color componants each range between 0.0f and 1.0f
*/
Color Ray::phong_diffuse(Vec3 &collision_point, Vec3 & norm, Material & mat, Scene & scene, Octree &octree) {
Color diffuse_color = Color();
Vec3 light_direction;
Light *curr_light;
pair<Vec3, SceneObject*> light_intersect;
for (int i = 0; i < (int)scene.getLights()->size(); i++) {
curr_light = scene.getLights()->at(i);
light_direction = Vec3(collision_point, curr_light->getPosition()).unit();
light_intersect = octree.collide(Ray(collision_point, light_direction, 0));
//light_intersect = collide(Ray(collision_point, light_direction, 0), (*scene.getSceneObjects()));
if (light_intersect.second == nullptr || light_intersect.second->getMaterial().is_transparent()) {
diffuse_color = (diffuse_color * (float)i) + Color(mat.get_color() * mat.get_phong_diffuse() * curr_light->get_diffuse() *
lambertian(collision_point, norm, light_direction)
);
diffuse_color = diffuse_color / ((float)(i + 1));
}
}
diffuse_color.normalise();
return diffuse_color;
}
/**
*\fn Color Ray::phong_specular(Vec3 &collision_point, Vec3 &norm, Material &mat, Light &light)
*\brief phong's specular reflection of this Ray, according to the normal vector of the collided SceneObject
* and its Material.
*\return a new Color giving the RGB color componants each range between 0.0f and 1.0f
*/
Color Ray::phong_specular(Vec3 &collision_point, Vec3 & norm, Material & mat, Scene & scene, Octree &octree) {
Color specular_color = Color();
Vec3 light_direction, reflected_light;
Light *curr_light;
pair<Vec3, SceneObject*> light_intersect, reflect_intersect;
for (int i = 0; i < (int)scene.getLights()->size(); i++) { // for each light in the scene, combine shadings for the current ray
curr_light = scene.getLights()->at(i);
light_direction = Vec3(collision_point, curr_light->getPosition()).unit();
light_intersect = octree.collide(Ray(collision_point, light_direction, 0));
//light_intersect = collide(Ray(collision_point, light_direction, 0), (*scene.getSceneObjects()));
if (light_intersect.second == nullptr || Vec3(light_intersect.first, collision_point).length() > 0.05f || mat.is_transparent()) {
reflected_light = (-light_direction).reflect(norm);
specular_color = (specular_color * (float)i) + (Color( curr_light->get_color() * mat.get_phong_specular() * curr_light->get_specular() *
pow(max(reflected_light * this->direction, 0.0f),
mat.get_phong_alpha())
));
specular_color = specular_color / ((float)(i + 1));
}
}
specular_color.normalise();
return specular_color;
}
/*
*\fn Color Ray::(Vec3 &collision_point, Vec3 & norm, Material & mat, Scene & scene)
*\brief calculate the color of a ray pointing to a particular collision point, according to Phong's model shading.
*\return the RGB color resulting of the Phong shading
*/
Color Ray::phong_shading(Scene & scene, Octree &octree)
{
Color amb, dif, spe, composition;
// collision detection
pair<Vec3, SceneObject*> intersection = octree.collide(*this);
//pair<Vec3, SceneObject*> intersection = collide(*this, (*scene.getSceneObjects()));
//if collision calculate shading
if (intersection.second != nullptr) {
//extraction informations of the collision
Material mat = intersection.second->getMaterial();
Vec3 collision_point = intersection.first,
norm = intersection.second->computeBump(intersection.first);
spe = phong_specular(collision_point, norm, mat, scene, octree);
if (!mat.is_transparent()) {
//calculate phong's components
amb = phong_ambiant(mat, scene);
dif = phong_diffuse(collision_point, norm, mat, scene, octree);
if (this->ttl <= 0) { //if end of life of ray return
composition = (amb / 3.0f) + (dif / 3.0f) + (spe / 3.0f);
}
else { // else combine with reflexion
Ray reflection = Ray(collision_point, -this->direction.reflect(norm), this->ttl - 1);
composition = amb * (0.80f / 3.0f) +
dif * (0.80f / 3.0f) +
spe * (0.80f / 3.0f) +
mat.get_phong_specular() * reflection.phong_shading(scene, octree) * 0.2f;
}
} else { //if ray enconters transparent object
if (this->ttl <= 0) {
composition = spe;
} else {
Ray refract = Ray(collision_point, this->direction.refract(norm, 1.0f, mat.get_refractive_index()), this->ttl-1);
composition = spe + refract.phong_shading(scene, octree);
}
}
// if no collision show scene background color
} else {
composition = scene.getBackground();
}
composition.normalise();
return composition;
}