-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRayTracer.cpp
214 lines (157 loc) · 5.82 KB
/
RayTracer.cpp
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include "RayTracer.h"
#include <typeinfo>
#include <iostream>
#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <random>
using namespace std;
#define EPS 1E-2
RayTracer::RayTracer(Scene * s, int maxd, int sm){
scene = s;
maxdepth = maxd;
samples = sm;
}
// This function determines the closest object that a ray intersects.
// The getIntersection() method is polymorphic. Please provide implementations
// for all the objects in your scene (see Object.h and Object.cpp).
Object * RayTracer::intersect(Ray r){
scene->startIteration();
Object * current = NULL;
Object * minObject = NULL;
Point inter;
//Initialize min to infinite point;
Point min = Point::Infinite();
while((current = scene->getNextObject()) != NULL){
inter = current->getIntersection(r);
if((inter - r.p).length() > 1E-6){
if((inter-r.p).length() < (min-r.p).length()){
min = inter;
minObject = current;
}
}
}
return minObject;
}
// Trace a ray recursively
Color RayTracer::trace(Ray r, int depth){
Color rad=Color(0.0,0.0,0.0,0.0);
// YOUR CODE FOR RECURSIVE RAY TRACING GOES HERE
// Calculate intersection P between ray and closest object
if (depth > this->maxdepth)
{
return rad; //End recurssion
}
Object* hitObj = intersect(r);
if (hitObj == NULL)
{
return rad; // No object not hit by ray
}
// Determine the material type of that object
Material* mat = hitObj->getMaterial();
Point intersection = hitObj->getIntersection(r);
rad = Phong(hitObj->getNormal(intersection), intersection, r, mat, hitObj);
// Recursive Reflection
if (mat->type == REFLECTIVE)
{
depth += 1;
Ray reflectedRay = r.reflect(hitObj->getNormal(intersection), intersection);
reflectedRay.p = reflectedRay.p + (reflectedRay.v * EPS); // Move along a smidge
rad = rad + RayTracer::trace(reflectedRay, depth);
}
//hitObj->getMaterial();
//return Shade(r, P, material);
return rad;
}
// Local Phong illumination at a point.
// Coded based of https://steveharveynz.wordpress.com/category/programming/c-raytracer/
Color RayTracer::Phong(Point normal, Point p, Ray r, Material * m, Object * o)
{
Color ret = Color(0.0, 0.0, 0.0, 1.0);
normal.normalize();
// YOUR CODE HERE.
// There is ambient lighting irrespective of shadow.
// For each Light Source L do:
// Point pointLight = scene->getNextLight();
vector <Point> pointLights = scene->lights;
Color LightColor = Color(1.0,1.0,1.0,1.0); // White light
//LightColor = LightColor + LightColor;
double LightPower = 0.33; // Should be based on distance to light maybe?
// Everything get hits by ambient light
Color ambientColor = m->getAmbient(p) * LightPower;
Color diffuse = Color(0.0, 0.0, 0.0, 1.0);
Color specularHighlight = Color(0.0, 0.0, 0.0, 1.0);
for (int i = 0 ;i < pointLights.size(); i++)
{
// If L visable
// Draw ray from light to object, end if blocked by an object
// Find Direction towards light
Point lightDirection = (pointLights[i] - p);
lightDirection.normalize();
Ray lightRay(p + lightDirection * EPS, lightDirection); // Ray from light to Object. Point in direction of light and make sure it hits a light
Object* hitObj = intersect(lightRay);
double reflectiveness = 1000.0 * m->kr;
// Check if in shadow
// Object should be in the way of the light
if (hitObj == NULL || (normal * lightDirection < 0))
{
// Add Difuse component
Color diffuseColor = m->getDiffuse(p);
// ret = ret + diffuseColor;
// // Add specular component
Color specularColor = m->getSpecular(p);
// ret = ret + specularColor;
//double distance = (pointLights[i] - p).length;
// Calc Diffuse
double lDotNormal = normal * lightDirection;
lDotNormal = lDotNormal < 0 ? 0.0f : lDotNormal; // Makes sure angle > 0
diffuse = diffuse + (diffuseColor * LightPower * lDotNormal);
diffuse = diffuse + (diffuseColor * LightPower * m ->kd * lDotNormal);
// Calc Specular
// SPECULAR
Point toCamera = r.v * -1;
toCamera.normalize();
Point disFromLight = toCamera + lightDirection;
disFromLight.normalize(); // divide by length
double specReflec = disFromLight * normal;
specReflec = specReflec < 0 ? 0.0f : specReflec; // Makes sure angle > 0
double refectivity = pow(specReflec, reflectiveness);
specularHighlight = specularHighlight + specularColor * LightPower * refectivity;
}
//else // In shadow, some object blocks light
{
// cout << "\n Lightx: " << pointLights[i].x << endl;
// cout << "\n Lighty: " << pointLights[i].y << endl;
// Calculate Radance, rad at point
// rad = rad + Radiance at point
// Code taken from Assignment 3 shader
//ret = ret + pointLights[i]
// Something blocking light path
}
}
// if (typeid(*o) == typeid(Triangle) )
// ret = Color(0.1,1.0,0.0,0.0);
// else
// ret = Color(0.1,1.0,1.0,0.0);
Color finalColor = ambientColor + diffuse + specularHighlight; // Add all components of light together
return finalColor;
}
// This function generates point on the image plane and starts a trace
// through them.
// Grid supersampling is also implemented.
Color RayTracer::calculate(int x, int y){
Color c = Color(0.0,0.0,0.0,0.0);
for(int i = 1; i <= samples; i++){
for(int j = 1; j <= samples; j++){
double one, two;
// We subtract 0.5 so that the (u,v)-origin is at the
//center of the image plane.
one = double(x)-0.5+double(i)/double(samples);
two = double(y)-0.5+double(j)/double(samples);
Ray r = scene->makeRay(one,two);
c = c+trace(r,0);
}
}
c = c*(1.0/double(samples*samples));
return c;
}