-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRecursiveRayTracer.cpp
124 lines (102 loc) · 3.58 KB
/
RecursiveRayTracer.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
#include "Tracer.h"
#include "RecursiveRayTracer.h"
#include "AppConstants.h"
#include "Colors.h"
#include "Material.h"
#include "Light.h"
RecursiveRayTracer::RecursiveRayTracer()
{
}
Color RecursiveRayTracer::traceSingleRay(const Ray& ray) const
{
return traceRayRecursively(ray, 0);
}
Color RecursiveRayTracer::traceRayRecursively(const Ray& ray, int depth) const
{
Hit hit = scene->getNearestIntersect(ray);
if (hitsNothing(hit)) return colors::BLACK;
if(maxDepthReached(depth)) return colors::CYAN;
Color outColor(0, 0, 0);
if (hitsDiffuse(hit) || hitsTextured(hit)) outColor += shadeDiffuse(hit);
if (hitsReflective(hit)) outColor += traceReflectedRay(ray, hit, depth);
if (hitsRefractive(hit)) outColor += traceRefractedRay(ray, hit, depth);
return outColor;
}
Color RecursiveRayTracer::shadeDiffuse(const Hit& hit) const
{
Color outColor(0, 0, 0);
std::vector<const Light*> lights = scene->getLights();
for (const Light* light : lights)
{
outColor += shadeHitpointWithSingleLight(hit, light);
}
return outColor;
}
Color RecursiveRayTracer::traceReflectedRay(const Ray& ray, const Hit& hit, int depth) const
{
const Material* material = hit.getMaterial();
Color frensel = Frensel(hit.getInDir(), hit.getNormal(), material->getColor());
Ray reflectedRay = ray.getReflectedRay(hit.getHitPoint(), hit.getNormal());
return traceRayRecursively(reflectedRay, depth + 1) * frensel;
}
Color RecursiveRayTracer::traceRefractedRay(const Ray& ray, const Hit& hit, int depth) const
{
const Material* material = hit.getMaterial();
Color frensel = Frensel(hit.getInDir(), hit.getNormal(), material->getColor());
Ray refractedRay = ray.getRefractedRay(hit.getHitPoint(), hit.getNormal(), material->getIor());
return traceRayRecursively(refractedRay, depth + 1) * (colors::WHITE - frensel);
}
Color RecursiveRayTracer::Frensel(const Vector3D& viewDir, const Vector3D& normal, const Color& color) const
{
float cosAlpha = fabs(DotProduct(normal, viewDir));
return color + (colors::WHITE - color) * pow((1 - cosAlpha), 5);
}
Color RecursiveRayTracer::shadeHitpointWithSingleLight(const Hit& hit, const Light* light) const
{
Point3D hitPoint = hit.getHitPoint();
Point3D lightPos = light->getPosition();
Ray shadowRay = Ray(hitPoint, lightPos);
float lightDist = hitPoint.getDistanceTo(lightPos);
if (pointIsShadowed(shadowRay, lightDist))
{
return colors::SHADOW_COLOR;
}
else
{
Vector3D lightDir = shadowRay.getDirection();
float lightIntensity = light->getIntensityInPoint(hitPoint);
Sample2D uvPoint = hit.getHitObject()->getUV(hitPoint);
Color materialColor = hit.getMaterial()->getColor(uvPoint.u, uvPoint.v);
float lambertian = CosTheta(hit.getNormal(), lightDir);
return light->getColor() * materialColor * lambertian * lightIntensity;
}
}
bool RecursiveRayTracer::pointIsShadowed(const Ray& shadowRay, float lightDist) const
{
float obstacleDist = scene->distanceOfNearestIntersect(shadowRay);
return obstacleDist < lightDist;
}
bool RecursiveRayTracer::hitsNothing(const Hit& hit) const
{
return hit.getHitObject() == nullptr;
}
bool RecursiveRayTracer::hitsDiffuse(const Hit& hit) const
{
return hit.getMaterial()->getType() == DIFFUSE;
}
bool RecursiveRayTracer::hitsTextured(const Hit& hit) const
{
return hit.getMaterial()->getType() == TEXTURED;
}
bool RecursiveRayTracer::hitsReflective(const Hit& hit) const
{
return hit.getMaterial()->getType() == REFLECTIVE;
}
bool RecursiveRayTracer::hitsRefractive(const Hit& hit) const
{
return hit.getMaterial()->getType() == REFRACTIVE;
}
bool RecursiveRayTracer::maxDepthReached(int bounces) const
{
return !(bounces < MAX_DEPTH);
}