Skip to content

Commit 7596c72

Browse files
committed
add task5
1 parent 7f17ac3 commit 7596c72

File tree

610 files changed

+206889
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

610 files changed

+206889
-0
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,12 @@ Add `#include <array>` in rasterizer.cpp
8080
## for task3
8181

8282
### You should use C++ 17
83+
8384
Set `C++ Language Dialect` to `C++ 17 [std=C++17]`
85+
8486
Set `C++ Standard Library` to `... LLVM C++ ...`
8587

88+
8689
### read file
8790
Another thing you have to know is Xcode not running your CPP code in your work directory, but a very deep path like `~/Library/Developer/Xcode/DerivedData/task3-ewyxlatyzwtvlgcrtquhcxutpryf/Build/Products/Debug`
8891

@@ -95,12 +98,21 @@ check this https://mmquant.net/working-directories-and-build-locations-with-xcod
9598
I am now using option2 for task3.
9699

97100
Set `Copy Files ---> Destination` to `Products Directory`
101+
98102
and set subpath to empty. Click `+` to choose your models folder.
103+
99104
After you click running, you will see models copied into `~/Library/Developer/Xcode/DerivedData/task3-ewyxlatyzwtvlgcrtquhcxutpryf/Build/Products/Debug`
100105

101106
### run with arguments
102107
`Product ---> Scheme ---> Edit Scheme`
103108

104109
First argument is `output.png`. Second argument is `texture or phone or normal ..`
105110

111+
## for task5
112+
### No template named 'optional' in namespace 'std'
113+
114+
Set `C++ Language Dialect` to `C++ 17 [std=C++17]`
115+
116+
Set `C++ Standard Library` to `... LLVM C++ ...`
117+
106118

task5/Assignment5/Code/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
project(RayTracing)
3+
4+
set(CMAKE_CXX_STANDARD 17)
5+
6+
add_executable(RayTracing main.cpp Object.hpp Vector.hpp Sphere.hpp global.hpp Triangle.hpp Scene.cpp Scene.hpp Light.hpp Renderer.cpp)
7+
target_compile_options(RayTracing PUBLIC -Wall -Wextra -pedantic -Wshadow -Wreturn-type -fsanitize=undefined)
8+
target_compile_features(RayTracing PUBLIC cxx_std_17)
9+
target_link_libraries(RayTracing PUBLIC -fsanitize=undefined)

task5/Assignment5/Code/Light.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#include "Vector.hpp"
4+
5+
class Light
6+
{
7+
public:
8+
Light(const Vector3f& p, const Vector3f& i)
9+
: position(p)
10+
, intensity(i)
11+
{}
12+
virtual ~Light() = default;
13+
Vector3f position;
14+
Vector3f intensity;
15+
};

task5/Assignment5/Code/Object.hpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#pragma once
2+
3+
#include "Vector.hpp"
4+
#include "global.hpp"
5+
6+
class Object
7+
{
8+
public:
9+
Object()
10+
: materialType(DIFFUSE_AND_GLOSSY)
11+
, ior(1.3)
12+
, Kd(0.8)
13+
, Ks(0.2)
14+
, diffuseColor(0.2)
15+
, specularExponent(25)
16+
{}
17+
18+
virtual ~Object() = default;
19+
20+
virtual bool intersect(const Vector3f&, const Vector3f&, float&, uint32_t&, Vector2f&) const = 0;
21+
22+
virtual void getSurfaceProperties(const Vector3f&, const Vector3f&, const uint32_t&, const Vector2f&, Vector3f&,
23+
Vector2f&) const = 0;
24+
25+
virtual Vector3f evalDiffuseColor(const Vector2f&) const
26+
{
27+
return diffuseColor;
28+
}
29+
30+
// material properties
31+
MaterialType materialType;
32+
float ior;
33+
float Kd, Ks;
34+
Vector3f diffuseColor;
35+
float specularExponent;
36+
};

task5/Assignment5/Code/Renderer.cpp

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
#include <fstream>
2+
#include "Vector.hpp"
3+
#include "Renderer.hpp"
4+
#include "Scene.hpp"
5+
#include <optional>
6+
7+
inline float deg2rad(const float &deg)
8+
{ return deg * M_PI/180.0; }
9+
10+
// Compute reflection direction
11+
Vector3f reflect(const Vector3f &I, const Vector3f &N)
12+
{
13+
return I - 2 * dotProduct(I, N) * N;
14+
}
15+
16+
// [comment]
17+
// Compute refraction direction using Snell's law
18+
//
19+
// We need to handle with care the two possible situations:
20+
//
21+
// - When the ray is inside the object
22+
//
23+
// - When the ray is outside.
24+
//
25+
// If the ray is outside, you need to make cosi positive cosi = -N.I
26+
//
27+
// If the ray is inside, you need to invert the refractive indices and negate the normal N
28+
// [/comment]
29+
Vector3f refract(const Vector3f &I, const Vector3f &N, const float &ior)
30+
{
31+
float cosi = clamp(-1, 1, dotProduct(I, N));
32+
float etai = 1, etat = ior;
33+
Vector3f n = N;
34+
if (cosi < 0) { cosi = -cosi; } else { std::swap(etai, etat); n= -N; }
35+
float eta = etai / etat;
36+
float k = 1 - eta * eta * (1 - cosi * cosi);
37+
return k < 0 ? 0 : eta * I + (eta * cosi - sqrtf(k)) * n;
38+
}
39+
40+
// [comment]
41+
// Compute Fresnel equation
42+
//
43+
// \param I is the incident view direction
44+
//
45+
// \param N is the normal at the intersection point
46+
//
47+
// \param ior is the material refractive index
48+
// [/comment]
49+
float fresnel(const Vector3f &I, const Vector3f &N, const float &ior)
50+
{
51+
float cosi = clamp(-1, 1, dotProduct(I, N));
52+
float etai = 1, etat = ior;
53+
if (cosi > 0) { std::swap(etai, etat); }
54+
// Compute sini using Snell's law
55+
float sint = etai / etat * sqrtf(std::max(0.f, 1 - cosi * cosi));
56+
// Total internal reflection
57+
if (sint >= 1) {
58+
return 1;
59+
}
60+
else {
61+
float cost = sqrtf(std::max(0.f, 1 - sint * sint));
62+
cosi = fabsf(cosi);
63+
float Rs = ((etat * cosi) - (etai * cost)) / ((etat * cosi) + (etai * cost));
64+
float Rp = ((etai * cosi) - (etat * cost)) / ((etai * cosi) + (etat * cost));
65+
return (Rs * Rs + Rp * Rp) / 2;
66+
}
67+
// As a consequence of the conservation of energy, transmittance is given by:
68+
// kt = 1 - kr;
69+
}
70+
71+
// [comment]
72+
// Returns true if the ray intersects an object, false otherwise.
73+
//
74+
// \param orig is the ray origin
75+
// \param dir is the ray direction
76+
// \param objects is the list of objects the scene contains
77+
// \param[out] tNear contains the distance to the cloesest intersected object.
78+
// \param[out] index stores the index of the intersect triangle if the interesected object is a mesh.
79+
// \param[out] uv stores the u and v barycentric coordinates of the intersected point
80+
// \param[out] *hitObject stores the pointer to the intersected object (used to retrieve material information, etc.)
81+
// \param isShadowRay is it a shadow ray. We can return from the function sooner as soon as we have found a hit.
82+
// [/comment]
83+
std::optional<hit_payload> trace(
84+
const Vector3f &orig, const Vector3f &dir,
85+
const std::vector<std::unique_ptr<Object> > &objects)
86+
{
87+
float tNear = kInfinity;
88+
std::optional<hit_payload> payload;
89+
for (const auto & object : objects)
90+
{
91+
float tNearK = kInfinity;
92+
uint32_t indexK;
93+
Vector2f uvK;
94+
if (object->intersect(orig, dir, tNearK, indexK, uvK) && tNearK < tNear)
95+
{
96+
payload.emplace();
97+
payload->hit_obj = object.get();
98+
payload->tNear = tNearK;
99+
payload->index = indexK;
100+
payload->uv = uvK;
101+
tNear = tNearK;
102+
}
103+
}
104+
105+
return payload;
106+
}
107+
108+
// [comment]
109+
// Implementation of the Whitted-style light transport algorithm (E [S*] (D|G) L)
110+
//
111+
// This function is the function that compute the color at the intersection point
112+
// of a ray defined by a position and a direction. Note that thus function is recursive (it calls itself).
113+
//
114+
// If the material of the intersected object is either reflective or reflective and refractive,
115+
// then we compute the reflection/refraction direction and cast two new rays into the scene
116+
// by calling the castRay() function recursively. When the surface is transparent, we mix
117+
// the reflection and refraction color using the result of the fresnel equations (it computes
118+
// the amount of reflection and refraction depending on the surface normal, incident view direction
119+
// and surface refractive index).
120+
//
121+
// If the surface is diffuse/glossy we use the Phong illumation model to compute the color
122+
// at the intersection point.
123+
// [/comment]
124+
Vector3f castRay(
125+
const Vector3f &orig, const Vector3f &dir, const Scene& scene,
126+
int depth)
127+
{
128+
if (depth > scene.maxDepth) {
129+
return Vector3f(0.0,0.0,0.0);
130+
}
131+
132+
Vector3f hitColor = scene.backgroundColor;
133+
if (auto payload = trace(orig, dir, scene.get_objects()); payload)
134+
{
135+
Vector3f hitPoint = orig + dir * payload->tNear;
136+
Vector3f N; // normal
137+
Vector2f st; // st coordinates
138+
payload->hit_obj->getSurfaceProperties(hitPoint, dir, payload->index, payload->uv, N, st);
139+
switch (payload->hit_obj->materialType) {
140+
case REFLECTION_AND_REFRACTION:
141+
{
142+
Vector3f reflectionDirection = normalize(reflect(dir, N));
143+
Vector3f refractionDirection = normalize(refract(dir, N, payload->hit_obj->ior));
144+
Vector3f reflectionRayOrig = (dotProduct(reflectionDirection, N) < 0) ?
145+
hitPoint - N * scene.epsilon :
146+
hitPoint + N * scene.epsilon;
147+
Vector3f refractionRayOrig = (dotProduct(refractionDirection, N) < 0) ?
148+
hitPoint - N * scene.epsilon :
149+
hitPoint + N * scene.epsilon;
150+
Vector3f reflectionColor = castRay(reflectionRayOrig, reflectionDirection, scene, depth + 1);
151+
Vector3f refractionColor = castRay(refractionRayOrig, refractionDirection, scene, depth + 1);
152+
float kr = fresnel(dir, N, payload->hit_obj->ior);
153+
hitColor = reflectionColor * kr + refractionColor * (1 - kr);
154+
break;
155+
}
156+
case REFLECTION:
157+
{
158+
float kr = fresnel(dir, N, payload->hit_obj->ior);
159+
Vector3f reflectionDirection = reflect(dir, N);
160+
Vector3f reflectionRayOrig = (dotProduct(reflectionDirection, N) < 0) ?
161+
hitPoint + N * scene.epsilon :
162+
hitPoint - N * scene.epsilon;
163+
hitColor = castRay(reflectionRayOrig, reflectionDirection, scene, depth + 1) * kr;
164+
break;
165+
}
166+
default:
167+
{
168+
// [comment]
169+
// We use the Phong illumation model int the default case. The phong model
170+
// is composed of a diffuse and a specular reflection component.
171+
// [/comment]
172+
Vector3f lightAmt = 0, specularColor = 0;
173+
Vector3f shadowPointOrig = (dotProduct(dir, N) < 0) ?
174+
hitPoint + N * scene.epsilon :
175+
hitPoint - N * scene.epsilon;
176+
// [comment]
177+
// Loop over all lights in the scene and sum their contribution up
178+
// We also apply the lambert cosine law
179+
// [/comment]
180+
for (auto& light : scene.get_lights()) {
181+
Vector3f lightDir = light->position - hitPoint;
182+
// square of the distance between hitPoint and the light
183+
float lightDistance2 = dotProduct(lightDir, lightDir);
184+
lightDir = normalize(lightDir);
185+
float LdotN = std::max(0.f, dotProduct(lightDir, N));
186+
// is the point in shadow, and is the nearest occluding object closer to the object than the light itself?
187+
auto shadow_res = trace(shadowPointOrig, lightDir, scene.get_objects());
188+
bool inShadow = shadow_res && (shadow_res->tNear * shadow_res->tNear < lightDistance2);
189+
190+
lightAmt += inShadow ? 0 : light->intensity * LdotN;
191+
Vector3f reflectionDirection = reflect(-lightDir, N);
192+
193+
specularColor += powf(std::max(0.f, -dotProduct(reflectionDirection, dir)),
194+
payload->hit_obj->specularExponent) * light->intensity;
195+
}
196+
197+
hitColor = lightAmt * payload->hit_obj->evalDiffuseColor(st) * payload->hit_obj->Kd + specularColor * payload->hit_obj->Ks;
198+
break;
199+
}
200+
}
201+
}
202+
203+
return hitColor;
204+
}
205+
206+
// [comment]
207+
// The main render function. This where we iterate over all pixels in the image, generate
208+
// primary rays and cast these rays into the scene. The content of the framebuffer is
209+
// saved to a file.
210+
// [/comment]
211+
void Renderer::Render(const Scene& scene)
212+
{
213+
std::vector<Vector3f> framebuffer(scene.width * scene.height);
214+
215+
float scale = std::tan(deg2rad(scene.fov * 0.5f));
216+
float imageAspectRatio = scene.width / (float)scene.height;
217+
218+
// Use this variable as the eye position to start your rays.
219+
Vector3f eye_pos(0);
220+
int m = 0;
221+
for (int j = 0; j < scene.height; ++j)
222+
{
223+
for (int i = 0; i < scene.width; ++i)
224+
{
225+
// generate primary ray direction
226+
float x;
227+
float y;
228+
// TODO: Find the x and y positions of the current pixel to get the direction
229+
// vector that passes through it.
230+
// Also, don't forget to multiply both of them with the variable *scale*, and
231+
// x (horizontal) variable with the *imageAspectRatio*
232+
233+
Vector3f dir = Vector3f(x, y, -1); // Don't forget to normalize this direction!
234+
framebuffer[m++] = castRay(eye_pos, dir, scene, 0);
235+
}
236+
UpdateProgress(j / (float)scene.height);
237+
}
238+
239+
// save framebuffer to file
240+
FILE* fp = fopen("binary.ppm", "wb");
241+
(void)fprintf(fp, "P6\n%d %d\n255\n", scene.width, scene.height);
242+
for (auto i = 0; i < scene.height * scene.width; ++i) {
243+
static unsigned char color[3];
244+
color[0] = (char)(255 * clamp(0, 1, framebuffer[i].x));
245+
color[1] = (char)(255 * clamp(0, 1, framebuffer[i].y));
246+
color[2] = (char)(255 * clamp(0, 1, framebuffer[i].z));
247+
fwrite(color, 1, 3, fp);
248+
}
249+
fclose(fp);
250+
}

task5/Assignment5/Code/Renderer.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
#include "Scene.hpp"
3+
4+
struct hit_payload
5+
{
6+
float tNear;
7+
uint32_t index;
8+
Vector2f uv;
9+
Object* hit_obj;
10+
};
11+
12+
class Renderer
13+
{
14+
public:
15+
void Render(const Scene& scene);
16+
17+
private:
18+
};

task5/Assignment5/Code/Scene.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//
2+
// Created by Göksu Güvendiren on 2019-05-14.
3+
//
4+
5+
#include "Scene.hpp"

0 commit comments

Comments
 (0)