-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRender.cpp
97 lines (79 loc) · 4.08 KB
/
Render.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
#include "Render.h"
Render::Render(Scene *scene, Screen screen, int height, int width) : scene(scene),
screen(screen), height(height),
width(width) {
calculatePixels();
}
void Render::calculatePixels() {
colorMap = std::vector<std::vector<Color>>(height, std::vector<Color>(width));
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
Point screenPoint = screen.leftBottomCorner +
screen.bottomToTop * (i * 1.0 / height) +
screen.leftToRight * (j * 1.0 / width);
Vector rayDirection = screenPoint - screen.camera;
colorMap[height - 1 - i][j] = traceRay(screen.camera, rayDirection, 1, 0);
}
}
}
bool Render::isVisible(Point rayStart, Vector rayDirection, Primitive *object) const {
Intersection intersection;
if (scene->findRayIntersection(rayStart, rayDirection, intersection)) {
return intersection.primitive == object &&
Point::doubleEqual(0, (intersection.point - (rayStart + rayDirection)).length());
}
return false;
}
double Render::countRayIntensity(const Intersection &intersection) const {
double rayIntensity = 0;
for (auto lightSource : scene->getLightSources()) {
if (isVisible(lightSource.getPosition(), intersection.point - lightSource.getPosition(),
intersection.primitive)) {
double incidence = intersection.surfaceNormal.normalise() %
(lightSource.getPosition() - intersection.point).normalise();
if (incidence > 0) {
rayIntensity += lightSource.getIntensity() * incidence /
(lightSource.getPosition() - intersection.point).squaredLength();
}
}
}
return rayIntensity;
}
Color Render::traceRay(Point &rayStart, Vector rayDirection, double intensity, int depth) const {
if (depth > maxDepth || intensity < minIntensity) {
return Color(0, 0, 0);
}
Intersection intersection;
if (scene->findRayIntersection(rayStart, rayDirection, intersection)) {
Color reflectedColor(0, 0, 0);
if (intersection.isFrontFace && intersection.primitive->getMaterial().getReflect() > 1e-3) {
Vector reflectedRayDirection = rayDirection.reflect(intersection.surfaceNormal);
reflectedColor = traceRay(intersection.point, reflectedRayDirection,
intensity * intersection.primitive->getMaterial().getReflect(), depth + 1);
}
if (Point::doubleEqual(intersection.primitive->getMaterial().getRefract(), 0)) {
double rayIntensity = countRayIntensity(intersection);
return intersection.color * rayIntensity * (1 - intersection.primitive->getMaterial().getReflect()) +
reflectedColor * intersection.primitive->getMaterial().getReflect();
}
else {
Vector refractedRayDirection;
if (intersection.isFrontFace) {
refractedRayDirection = rayDirection.refract(intersection.surfaceNormal,
intersection.primitive->getMaterial().getRefract());
}
else {
refractedRayDirection = rayDirection.refract(intersection.surfaceNormal,
1 / intersection.primitive->getMaterial().getRefract());
}
Color refractedColor = traceRay(intersection.point, refractedRayDirection,
intensity * (1 - intersection.primitive->getMaterial().getReflect()),
depth + 1);
return refractedColor * (1 - intersection.primitive->getMaterial().getReflect()) +
reflectedColor * intersection.primitive->getMaterial().getReflect();
}
}
else {
return Color(0.05, 0.05, 0.05);
}
}