Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Tobias 2022-11-15 13:25:27 +01:00
commit 48f338dd7c
30 changed files with 482 additions and 473 deletions

12
.gitignore vendored
View file

@ -6,8 +6,11 @@ build/
/data/*
!/data/README.txt
!/data/fireplace
!/data/subdiv
!/data/parallax
!/data/fractal.obj
/result*
/cmake-build-debug
# Latex stuff
*.aux
@ -17,4 +20,9 @@ build/
*.out
*.pdf
*.synctex.gz
*.json
*.json
*__latexindent_temp.tex
# Mac Stuff
.DS_Store

View file

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.5)
project(CG1_Tracer LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT WIN32)
@ -38,3 +38,7 @@ target_link_libraries(tracey_ex1 tracey)
add_executable(tracey_ex2 ex2.cpp)
target_link_libraries(tracey_ex2 tracey)

View file

@ -1,3 +1,6 @@
# Build / Setup Prozess
Anweisungen ausgelagert in [BUILD_INSTRUCTIONS.md](BUILD_INSTRUCTIONS.md)
# Git Grundlagen / Workflow
Git Spickzettel: https://files.morr.cc/git-spickzettel.png
@ -8,7 +11,7 @@ Angepasst von https://medium.com/@topspinj/how-to-git-rebase-into-a-forked-repo-
Das Musterlösungs-Repository als remote mit Namen _upstream_ (oder ähnlich) hinzufügen:
`git remote add upstream gogs@git.cg.cs.tu-bs.de:CG1/WS2021.git`
`git remote add upstream gogs@git.cg.cs.tu-bs.de:CG1_WS2223/Base.git`
Alle Branches von _upstream_ und deren Änderungen herunterladen
@ -32,4 +35,4 @@ hier kann man dann noch ggf. selbst Hand anlegen und die Änderungen dann wieder
`git push origin master`
evtl. muss noch `--force` angegeben werden
evtl. muss noch `--force` angegeben werden

View file

@ -1,20 +1,8 @@
#include "camera/perspectivecamera.h"
#include <cmath>
PerspectiveCamera::PerspectiveCamera() : forwardDirection(0, 0, 1), upDirection(0, 1, 0), fovAngle(70) {}
PerspectiveCamera::PerspectiveCamera() : forwardDirection(0, 0, 1), upDirection(0, 1, 0), rightDirection(1, 0, 0) { setFovAngle(70); }
Ray PerspectiveCamera::createRay(float x, float y) const {
// Set up a left-handed coordinate system,
// in which the camera looks along the positive z-Axis
Vector3d normalVector = normalized(crossProduct(upDirection, forwardDirection));
// Orthogonolize upDirection, to avoid skewing the image
Vector3d orthogonalUpDirection = -crossProduct(normalVector, forwardDirection);
Vector3d normalVector_fov = normalVector * std::abs(tan(this->fovAngle / 360.0f * PI));
Vector3d upVector_fov = orthogonalUpDirection * std::abs(tan(this->fovAngle / 360.0f * PI));
Vector3d directionVector = normalized(forwardDirection + x * normalVector_fov + y * upVector_fov);
return Ray {this->position, directionVector};
// Create the ray
return Ray(this->position, x * this->rightDirection + y * this->upDirection + focus * this->forwardDirection);
}

View file

@ -12,9 +12,26 @@ public:
// Set
void setPosition(Vector3d const &position) { this->position = position; }
void setForwardDirection(Vector3d const &forwardDirection) { this->forwardDirection = normalized(forwardDirection); }
void setUpDirection(Vector3d const &upDirection) { this->upDirection = normalized(upDirection); }
void setFovAngle(float fovAngle) { this->fovAngle = fovAngle; }
void setForwardDirection(Vector3d const &forwardDirection) {
// IMPLEMENT ME
// Set up a left-handed coordinate system,
// in which the camera looks along the positive z-Axis
// Set up a left-handed coordinate system,
// in which the camera looks along the positive z-Axis
std::tie(this->forwardDirection, this->upDirection, this->rightDirection) = orthoNormalized(forwardDirection, this->upDirection, crossProduct(this->upDirection, forwardDirection));
}
void setUpDirection(Vector3d const &upDirection) {
// IMPLEMENT ME
// Set up a left-handed coordinate system,
// in which the camera looks along the positive z-Axis
// Set up a left-handed coordinate system,
// in which the camera looks along the positive z-Axis
std::tie(this->forwardDirection, this->upDirection, this->rightDirection) = orthoNormalized(this->forwardDirection, upDirection, crossProduct(upDirection, this->forwardDirection));
}
void setFovAngle(float fovAngle) {
// Calculate the focus
this->focus = 1.0f / std::tan((fovAngle * PI / 180) / 2.0f);
}
// Camera functions
Ray createRay(float x, float y) const override;
@ -23,7 +40,8 @@ protected:
Vector3d position;
Vector3d forwardDirection;
Vector3d upDirection;
float fovAngle;
Vector3d rightDirection;
float focus;
};
#endif

View file

@ -4,7 +4,23 @@
#include <cmath>
#ifndef EPSILON
#define EPSILON 1E-4f
#define EPSILON 1E-6f
#endif
#ifndef SPLT_EPS
#define SPLT_EPS 4 * EPSILON
#endif
#ifndef LGT_EPS
#define LGT_EPS 5E-5f
#endif
#ifndef REFR_EPS
#define REFR_EPS 1E-4f
#endif
#ifndef NORM_EPS
#define NORM_EPS 1E-12f
#endif
#ifndef INFINITY

3
common/ray.cpp Normal file
View file

@ -0,0 +1,3 @@
#include "ray.h"
int Ray::rayCount = 0;

View file

@ -23,10 +23,14 @@ struct Ray {
Vector3d bitangent;
// Constructor
Ray(Vector3d const &origin = Vector3d(0, 0, 0), Vector3d const &direction = Vector3d(0, 0, 1))
: origin(origin), direction(normalized(direction)) {
Ray(Vector3d const &origin = Vector3d(0, 0, 0), Vector3d const &direction = Vector3d(0, 0, 1)) : origin(origin), direction(normalized(direction)) {
++rayCount;
}
inline int getRemainingBounces() const { return remainingBounces; }
static inline void resetRayCount() { rayCount = 0; }
static inline int getRayCount() { return rayCount; }
private:
#ifndef ICG_RAY_BOUNCES
@ -35,6 +39,7 @@ private:
int remainingBounces = ICG_RAY_BOUNCES;
#endif
static int rayCount;
};
#endif

View file

@ -1,6 +1,7 @@
#include "common/vector2d.h"
#include "common/common.h"
#include <algorithm>
#include <cassert>
#include <cmath>
// Access operators ////////////////////////////////////////////////////////////
@ -76,18 +77,14 @@ Vector2d &operator/=(Vector2d &left, float right) {
// Useful functions ////////////////////////////////////////////////////////////
Vector2d componentProduct(const Vector2d &left, const Vector2d &right) {
return Vector2d(left.u * right.u, left.v * right.v);
}
Vector2d componentProduct(const Vector2d &left, const Vector2d &right) { return Vector2d(left.u * right.u, left.v * right.v); }
Vector2d componentQuotient(const Vector2d &left, const Vector2d &right) {
return Vector2d(left.u / right.u, left.v / right.v);
}
Vector2d componentQuotient(const Vector2d &left, const Vector2d &right) { return Vector2d(left.u / right.u, left.v / right.v); }
float dotProduct(Vector2d const &left, Vector2d const &right) { return left.u * right.u + left.v * right.v; }
float length(Vector2d const &c) { return std::sqrt(dotProduct(c, c)); }
Vector2d normalized(Vector2d const &v) { return v / length(v); }
Vector2d normalized(Vector2d const &v) { return v / std::max(length(v), NORM_EPS); }
void normalize(Vector2d *v) { *v = normalized(*v); }

View file

@ -1,6 +1,7 @@
#include "common/vector3d.h"
#include "common/common.h"
#include <algorithm>
#include <cassert>
#include <cmath>
// Access operators ////////////////////////////////////////////////////////////
@ -34,35 +35,27 @@ float const &Vector3d::operator[](int const dimension) const {
// Comparison operators ////////////////////////////////////////////////////////
bool operator==(Vector3d const &left, Vector3d const &right) {
return (left.x == right.x && left.y == right.y && left.z == right.z);
}
bool operator==(Vector3d const &left, Vector3d const &right) { return (left.x == right.x && left.y == right.y && left.z == right.z); }
bool operator!=(Vector3d const &left, Vector3d const &right) { return !(left == right); }
// Arithmetic operators ////////////////////////////////////////////////////////
Vector3d operator+(Vector3d const &left, Vector3d const &right) {
return Vector3d(left.x + right.x, left.y + right.y, left.z + right.z);
}
Vector3d operator+(Vector3d const &left, Vector3d const &right) { return Vector3d(left.x + right.x, left.y + right.y, left.z + right.z); }
Vector3d operator-(Vector3d const &right) { return Vector3d(-right.x, -right.y, -right.z); }
Vector3d operator-(Vector3d const &left, Vector3d const &right) {
return Vector3d(left.x - right.x, left.y - right.y, left.z - right.z);
}
Vector3d operator-(Vector3d const &left, Vector3d const &right) { return Vector3d(left.x - right.x, left.y - right.y, left.z - right.z); }
Vector3d operator*(Vector3d const &left, float right) {
return Vector3d(left.x * right, left.y * right, left.z * right);
}
Vector3d operator*(Vector3d const &left, float right) { return Vector3d(left.x * right, left.y * right, left.z * right); }
Vector3d operator*(float left, Vector3d const &right) {
return Vector3d(left * right.x, left * right.y, left * right.z);
}
Vector3d operator*(float left, Vector3d const &right) { return Vector3d(left * right.x, left * right.y, left * right.z); }
Vector3d operator/(Vector3d const &left, float right) {
return Vector3d(left.x / right, left.y / right, left.z / right);
}
Vector3d operator*(Vector3d const &left, Vector3d const &right) { return Vector3d(left.x * right.x, left.y * right.y, left.z * right.z); }
Vector3d operator/(Vector3d const &left, float right) { return Vector3d(left.x / right, left.y / right, left.z / right); }
Vector3d operator/(Vector3d const &left, Vector3d const &right) { return Vector3d(left.x / right.x, left.y / right.y, left.z / right.z); }
// Assignment operators ////////////////////////////////////////////////////////
@ -87,6 +80,13 @@ Vector3d &operator*=(Vector3d &left, float right) {
return left;
}
Vector3d &operator*=(Vector3d &left, Vector3d const &right) {
left.x *= right.x;
left.y *= right.y;
left.z *= right.z;
return left;
}
Vector3d &operator/=(Vector3d &left, float right) {
left.x /= right;
left.y /= right;
@ -94,27 +94,34 @@ Vector3d &operator/=(Vector3d &left, float right) {
return left;
}
Vector3d &operator/=(Vector3d &left, Vector3d const &right) {
left.x /= right.x;
left.y /= right.y;
left.z /= right.z;
return left;
}
// Useful functions ////////////////////////////////////////////////////////////
Vector3d componentProduct(const Vector3d &left, const Vector3d &right) {
return Vector3d(left.x * right.x, left.y * right.y, left.z * right.z);
}
Vector3d componentProduct(const Vector3d &left, const Vector3d &right) { return Vector3d(left.x * right.x, left.y * right.y, left.z * right.z); }
Vector3d componentQuotient(const Vector3d &left, const Vector3d &right) {
return Vector3d(left.x / right.x, left.y / right.y, left.z / right.z);
}
Vector3d componentQuotient(const Vector3d &left, const Vector3d &right) { return Vector3d(left.x / right.x, left.y / right.y, left.z / right.z); }
Vector3d crossProduct(Vector3d const &left, Vector3d const &right) {
return Vector3d(left.y * right.z - left.z * right.y, left.z * right.x - left.x * right.z,
left.x * right.y - left.y * right.x);
}
Vector3d crossProduct(Vector3d const &left, Vector3d const &right) { return Vector3d(left.y * right.z - left.z * right.y, left.z * right.x - left.x * right.z, left.x * right.y - left.y * right.x); }
float dotProduct(Vector3d const &left, Vector3d const &right) {
return left.x * right.x + left.y * right.y + left.z * right.z;
}
float dotProduct(Vector3d const &left, Vector3d const &right) { return left.x * right.x + left.y * right.y + left.z * right.z; }
float length(Vector3d const &v) { return std::sqrt(dotProduct(v, v)); }
Vector3d normalized(Vector3d const &v) { return v / length(v); }
Vector3d normalized(Vector3d const &v) { return v / std::max(length(v), NORM_EPS); }
void normalize(Vector3d *v) { *v = normalized(*v); }
std::tuple<Vector3d, Vector3d, Vector3d> orthoNormalized(Vector3d const &u, Vector3d const &v, Vector3d const &w) {
// using gram-schmidt orthonormalization
auto ret_u = normalized(u);
auto ret_v = normalized(v - dotProduct(ret_u, v) * ret_u);
auto ret_w = normalized(w - dotProduct(ret_u, w) * ret_u - dotProduct(ret_v, w) * ret_v);
return std::make_tuple(ret_u, ret_v, ret_w);
}

View file

@ -1,6 +1,8 @@
#ifndef VECTOR3D_H
#define VECTOR3D_H
#include <tuple>
struct Vector3d {
// Components
float x, y, z;
@ -27,13 +29,17 @@ Vector3d operator-(Vector3d const &right);
Vector3d operator-(Vector3d const &left, Vector3d const &right);
Vector3d operator*(Vector3d const &left, float right);
Vector3d operator*(float left, Vector3d const &right);
Vector3d operator*(Vector3d const &left, Vector3d const &right);
Vector3d operator/(Vector3d const &left, float right);
Vector3d operator/(Vector3d const &left, Vector3d const &right);
// Assignment operators
Vector3d &operator+=(Vector3d &left, Vector3d const &right);
Vector3d &operator-=(Vector3d &left, Vector3d const &right);
Vector3d &operator*=(Vector3d &left, float right);
Vector3d &operator*=(Vector3d &left, Vector3d const &right);
Vector3d &operator/=(Vector3d &left, float right);
Vector3d &operator/=(Vector3d &left, Vector3d const &right);
// Useful functions
Vector3d componentProduct(Vector3d const &left, Vector3d const &right);
@ -43,5 +49,6 @@ float dotProduct(Vector3d const &left, Vector3d const &right);
float length(Vector3d const &v);
Vector3d normalized(Vector3d const &v);
void normalize(Vector3d *v);
std::tuple<Vector3d, Vector3d, Vector3d> orthoNormalized(Vector3d const &u, Vector3d const &v, Vector3d const &w);
#endif

62
ex1.cpp
View file

@ -11,42 +11,42 @@
#include "shader/flatshader.h"
int main() {
// Let's create a simple cornell box scene...
SimpleScene scene;
// Let's create a simple cornell box scene...
SimpleScene scene;
// Add shaders for the walls
auto red = std::make_shared<FlatShader>(Color(1.0f, 0.3f, 0.2f));
auto white = std::make_shared<FlatShader>(Color(1.0f, 1.0f, 1.0f));
auto blue = std::make_shared<FlatShader>(Color(0.2f, 0.3f, 1.0f));
// Add shaders for the walls
auto red = std::make_shared<FlatShader>(Color(1.0f, 0.3f, 0.2f));
auto white = std::make_shared<FlatShader>(Color(1.0f, 1.0f, 1.0f));
auto blue = std::make_shared<FlatShader>(Color(0.2f, 0.3f, 1.0f));
// Add shaders for the objects
auto green = std::make_shared<FlatShader>(Color(0.0f, 1.0f, 0.0f));
auto purple = std::make_shared<FlatShader>(Color(0.5f, 0.2f, 1.0f));
auto orange = std::make_shared<FlatShader>(Color(1.0f, 0.5f, 0.0f));
// Add shaders for the objects
auto green = std::make_shared<FlatShader>(Color(0.0f, 1.0f, 0.0f));
auto purple = std::make_shared<FlatShader>(Color(0.5f, 0.2f, 1.0f));
auto orange = std::make_shared<FlatShader>(Color(1.0f, 0.5f, 0.0f));
// Set up the cornell box walls
scene.add(std::make_shared<InfinitePlane>(Vector3d(0.0f, 0.0f, +5.0f), Vector3d(0.0f, 0.0f, -1.0f), purple));
scene.add(std::make_shared<InfinitePlane>(Vector3d(0.0f, 0.0f, -5.0f), Vector3d(0.0f, 0.0f, +1.0f), purple));
scene.add(std::make_shared<InfinitePlane>(Vector3d(0.0f, +5.0f, 0.0f), Vector3d(0.0f, -1.0f, 0.0f), white));
scene.add(std::make_shared<InfinitePlane>(Vector3d(0.0f, -5.0f, 0.0f), Vector3d(0.0f, +1.0f, 0.0f), white));
scene.add(std::make_shared<InfinitePlane>(Vector3d(+5.0f, 0.0f, 0.0f), Vector3d(-1.0f, 0.0f, 0.0f), blue));
scene.add(std::make_shared<InfinitePlane>(Vector3d(-5.0f, 0.0f, 0.0f), Vector3d(+1.0f, 0.0f, 0.0f), red));
// Set up the cornell box walls
scene.add(std::make_shared<InfinitePlane>(Vector3d(0.0f, 0.0f, +5.0f), Vector3d(0.0f, 0.0f, -1.0f), purple));
scene.add(std::make_shared<InfinitePlane>(Vector3d(0.0f, 0.0f, -5.0f), Vector3d(0.0f, 0.0f, +1.0f), purple));
scene.add(std::make_shared<InfinitePlane>(Vector3d(0.0f, +5.0f, 0.0f), Vector3d(0.0f, -1.0f, 0.0f), white));
scene.add(std::make_shared<InfinitePlane>(Vector3d(0.0f, -5.0f, 0.0f), Vector3d(0.0f, +1.0f, 0.0f), white));
scene.add(std::make_shared<InfinitePlane>(Vector3d(+5.0f, 0.0f, 0.0f), Vector3d(-1.0f, 0.0f, 0.0f), blue));
scene.add(std::make_shared<InfinitePlane>(Vector3d(-5.0f, 0.0f, 0.0f), Vector3d(+1.0f, 0.0f, 0.0f), red));
// Add a sphere
scene.add(std::make_shared<Sphere>(Vector3d(-3.0f, 0.0f, 0.0f), 1.5f, green));
scene.add(std::make_shared<Triangle>(Vector3d(0.0f, -5.0f, -4.0f), Vector3d(0.0f, -3.0f, 0.0f),
Vector3d(5.0f, -2.0f, -3.0f), orange));
// Add a sphere
scene.add(std::make_shared<Sphere>(Vector3d(-3.0f, 0.0f, 0.0f), 1.5f, green));
scene.add(std::make_shared<Triangle>(Vector3d(0.0f, -5.0f, -4.0f), Vector3d(0.0f, -3.0f, 0.0f),
Vector3d(5.0f, -2.0f, -3.0f), orange));
// Set up the camera
PerspectiveCamera camera;
camera.setFovAngle(70);
camera.setPosition(Vector3d(-2.5f, 2.5f, -10.0f));
camera.setForwardDirection(Vector3d(0.25f, -0.33f, 1.0f));
camera.setUpDirection(Vector3d(0.2f, 1.0f, 0.0f));
// Set up the camera
PerspectiveCamera camera;
camera.setFovAngle(70);
camera.setPosition(Vector3d(-2.5f, 2.5f, -10.0f));
camera.setForwardDirection(Vector3d(0.25f, -0.33f, 1.0f));
camera.setUpDirection(Vector3d(0.2f, 1.0f, 0.0f));
// Render the scene
SimpleRenderer renderer;
renderer.renderImage(scene, camera, 512, 512).save("result.png");
// Render the scene
SimpleRenderer renderer;
renderer.renderImage(scene, camera, 512, 512).save("result.png");
return 0;
return 0;
}

63
ex2.cpp
View file

@ -15,43 +15,42 @@
#include "light/pointlight.h"
int main()
{
// Let's create a simple cornell box scene...
SimpleScene scene;
scene.setEnvironmentMap(std::make_shared<Texture>("data/lion_env.png"));
int main() {
// Let's create a simple cornell box scene...
SimpleScene scene;
scene.setEnvironmentMap(std::make_shared<Texture>("data/lion_env.png"));
auto mirror = std::make_shared<MirrorShader>();
auto glass = std::make_shared<RefractionShader>(1.31f, 1.0f);
auto mirror = std::make_shared<MirrorShader>();
auto glass = std::make_shared<RefractionShader>(1.31f, 1.0f);
// add some lights
scene.add(std::make_shared<PointLight>(Vector3d(0.0f, 10.0f, -10.0f), 250.f, Color(1.0f, 1.0f, 1.0f)));
scene.add(std::make_shared<PointLight>(Vector3d(0.0f, 10.0f, 10.0f), 250.f, Color(1.0f, 1.0f, 1.0f)));
// add some lights
scene.add(std::make_shared<PointLight>(Vector3d(0.0f, 10.0f, -10.0f), 250.f, Color(1.0f, 1.0f, 1.0f)));
scene.add(std::make_shared<PointLight>(Vector3d(0.0f, 10.0f, 10.0f), 250.f, Color(1.0f, 1.0f, 1.0f)));
// Add shaders for the objects
auto orange = std::make_shared<SimpleShadowShader>(Color(1.0f, 0.5f, 0.0f));
auto red = std::make_shared<SimpleShadowShader>(Color(1.0f, 0.3f, 0.2f));
// Add shaders for the objects
auto orange = std::make_shared<SimpleShadowShader>(Color(1.0f, 0.5f, 0.0f));
auto red = std::make_shared<SimpleShadowShader>(Color(1.0f, 0.3f, 0.2f));
// Add objects
scene.add(std::make_shared<Sphere>(Vector3d(-3.0f, 0.0f, 0.0f), 1.5f, glass));
scene.add(std::make_shared<Box>(Vector3d(3.5f, -1.0f, 0.0f), Vector3d(3.0f, 3.0f, 3.0f), mirror));
scene.add(std::make_shared<Triangle>(Vector3d(5.0f, -5.0f, 5.0f), Vector3d(-10.0f, -5.0f, 10.0f),
Vector3d(-2.0f, -5.0f, -2.0f), orange));
scene.add(std::make_shared<Triangle>(Vector3d(-2.0f, -5.0f, -2.0f), Vector3d(10.0f, -5.0f, -10.0f),
Vector3d(5.0f, -5.0f, 5.0f), orange));
scene.add(std::make_shared<Triangle>(Vector3d(0.0f, -2.0f, 0.0f), Vector3d(2.0f, -2.0f, 0.0f),
Vector3d(0.0f, 0.0f, 0.0f), red));
// Add objects
scene.add(std::make_shared<Sphere>(Vector3d(-3.0f, 0.0f, 0.0f), 1.5f, glass));
scene.add(std::make_shared<Box>(Vector3d(3.5f, -1.0f, 0.0f), Vector3d(3.0f, 3.0f, 3.0f), mirror));
scene.add(std::make_shared<Triangle>(Vector3d(5.0f, -5.0f, 5.0f), Vector3d(-10.0f, -5.0f, 10.0f),
Vector3d(-2.0f, -5.0f, -2.0f), orange));
scene.add(std::make_shared<Triangle>(Vector3d(-2.0f, -5.0f, -2.0f), Vector3d(10.0f, -5.0f, -10.0f),
Vector3d(5.0f, -5.0f, 5.0f), orange));
scene.add(std::make_shared<Triangle>(Vector3d(0.0f, -2.0f, 0.0f), Vector3d(2.0f, -2.0f, 0.0f),
Vector3d(0.0f, 0.0f, 0.0f), red));
// Set up the camera
PerspectiveCamera camera;
camera.setFovAngle(70.0f);
camera.setPosition(Vector3d(-2.5f, 2.5f, -10.0f));
camera.setForwardDirection(Vector3d(0.4f, -0.33f, 1.0f));
camera.setUpDirection(Vector3d(0.0f, 1.0f, 0.0f));
// Set up the camera
PerspectiveCamera camera;
camera.setFovAngle(70.0f);
camera.setPosition(Vector3d(-2.5f, 2.5f, -10.0f));
camera.setForwardDirection(Vector3d(0.4f, -0.33f, 1.0f));
camera.setUpDirection(Vector3d(0.0f, 1.0f, 0.0f));
// Render the scene
SimpleRenderer renderer;
renderer.renderImage(scene, camera, 1024, 768).save("result.png");
// Render the scene
SimpleRenderer renderer;
renderer.renderImage(scene, camera, 1024, 768).save("result.png");
return 0;
return 0;
}

View file

@ -3,22 +3,21 @@
PointLight::PointLight(Vector3d const &position, float intensity, Color const &color) : Light(intensity, color), position(position) {}
Light::Illumination PointLight::illuminate(Scene const &scene, Ray const &ray) const
{
// IMPLEMENT ME
// Get the point on the surface
Light::Illumination PointLight::illuminate(Scene const &scene, Ray const &ray) const {
// IMPLEMENT ME
// Get the point on the surface
// Create an instance of the Illumination object, fill in the direction (from
// surface point to light source)
Light::Illumination illum;
// Create an instance of the Illumination object, fill in the direction (from
// surface point to light source)
Light::Illumination illum;
// Define a secondary ray from the surface point to the light source.
// Define a secondary ray from the surface point to the light source.
// If the target is not in shadow... (use scene.findOcclusion())
// If the target is not in shadow... (use scene.findOcclusion())
// Compute the brightness-color of this light using inverse squared distance
// to light source (i.e. 1/(d^2)), the color of this light source and the
// intensity
// Compute the brightness-color of this light using inverse squared distance
// to light source (i.e. 1/(d^2)), the color of this light source and the
// intensity
return illum;
return illum;
}

View file

@ -3,20 +3,19 @@
#include "light/light.h"
class PointLight : public Light
{
class PointLight : public Light {
public:
PointLight(Vector3d const &position, float intensity, Color const &color = Color(1, 1, 1));
PointLight(Vector3d const &position, float intensity, Color const &color = Color(1, 1, 1));
// Set
void setPosition(Vector3d const &position) { this->position = position; }
// Set
void setPosition(Vector3d const &position) { this->position = position; }
// Light functions
Illumination illuminate(Scene const &scene, Ray const &ray) const override;
// Light functions
Illumination illuminate(Scene const &scene, Ray const &ray) const override;
protected:
Vector3d position;
Vector3d position;
};
#endif

View file

@ -10,84 +10,22 @@ Box::Box(std::shared_ptr<Shader> const &shader) : Primitive(shader), size(Vector
Box::Box(Vector3d const &center, Vector3d const &size, std::shared_ptr<Shader> const &shader)
: Primitive(shader), center(center), size(size) {}
// Helper functions /////////////////////////////////////////////////////////
float intersectionParameterDimension(Vector3d bounds, Ray &ray, int dimension)
{
return (bounds[dimension] - ray.origin[dimension]) / ray.direction[dimension];
}
Vector3d intersectionParameter(Vector3d bounds, Ray &ray)
{
return Vector3d(intersectionParameterDimension(bounds, ray, 0),
intersectionParameterDimension(bounds, ray, 1),
intersectionParameterDimension(bounds, ray, 2));
}
// Primitive functions /////////////////////////////////////////////////////////
bool Box::intersect(Ray &ray) const
{
// IMPLEMENT ME!
bool Box::intersect(Ray &ray) const {
// IMPLEMENT ME!
// Determine whether the ray intersects the box
// Determine whether the ray intersects the box
Vector3d minBounds(this->minimumBounds(0), this->minimumBounds(1), this->minimumBounds(2));
Vector3d maxBounds(this->maximumBounds(0), this->maximumBounds(1), this->maximumBounds(2));
// Test whether this is the foremost primitive in front of the camera
Vector3d tMin = intersectionParameter(minBounds, ray);
Vector3d tMax = intersectionParameter(maxBounds, ray);
// (Optional for now) Calculate the normal
Vector3d tInAll = Vector3d(std::min(tMin[0], tMax[0]), std::min(tMin[1], tMax[1]), std::min(tMin[2], tMax[2]));
Vector3d tOutAll = Vector3d(std::max(tMin[0], tMax[0]), std::max(tMin[1], tMax[1]), std::max(tMin[2], tMax[2]));
// (Optional for now) Calculate the surface position
float tIn = std::max(std::max(tInAll[0], tInAll[1]), tInAll[2]);
float tOut = std::min(std::min(tOutAll[0], tOutAll[1]), tOutAll[2]);
// Set the new length and the current primitive
if (tIn > tOut || tOut < 0)
{
return false;
}
float t = tIn;
// Test whether this is the foremost primitive in front of the camera
if (t >= ray.length)
{
return false;
}
// (Optional for now) Calculate the normal
// On what side of the box did the ray hit?
Vector3d normal;
if (tInAll[0] == tIn)
{
normal = Vector3d(1, 0, 0);
}
else if (tInAll[1] == tIn)
{
normal = Vector3d(0, 1, 0);
}
else // tInAll[2] == tIn
{
normal = Vector3d(0, 0, 1);
}
// Make sure sign is correct
if (dotProduct(ray.direction, normal) > 0)
{
normal = -normal;
}
ray.normal = normalized(normal);
// (Optional for now) Calculate the surface position
// Set the new length and the current primitive
ray.length = t;
ray.primitive = this;
return false;
return false;
}
// Bounding box ////////////////////////////////////////////////////////////////

View file

@ -3,28 +3,27 @@
#include "primitive/primitive.h"
class Box : public Primitive
{
class Box : public Primitive {
public:
// Constructor
Box(std::shared_ptr<Shader> const &shader);
Box(Vector3d const &center, Vector3d const &size, std::shared_ptr<Shader> const &shader);
// Constructor
Box(std::shared_ptr<Shader> const &shader);
Box(Vector3d const &center, Vector3d const &size, std::shared_ptr<Shader> const &shader);
// Set
void setCenter(Vector3d const &center) { this->center = center; }
void setSize(Vector3d const &size) { this->size = size; }
// Set
void setCenter(Vector3d const &center) { this->center = center; }
void setSize(Vector3d const &size) { this->size = size; }
// Primitive functions
bool intersect(Ray &ray) const override;
// Primitive functions
bool intersect(Ray &ray) const override;
// Bounding box
float minimumBounds(int dimension) const override;
float maximumBounds(int dimension) const override;
// Bounding box
float minimumBounds(int dimension) const override;
float maximumBounds(int dimension) const override;
protected:
Vector3d center;
Vector3d size;
Vector3d center;
Vector3d size;
};
#endif

View file

@ -3,72 +3,52 @@
// Constructor /////////////////////////////////////////////////////////////////
InfinitePlane::InfinitePlane(std::shared_ptr<Shader> const &shader) : Primitive(shader), normal(0, 1, 0)
{}
InfinitePlane::InfinitePlane(std::shared_ptr<Shader> const &shader) : Primitive(shader), normal(0, 1, 0) {}
InfinitePlane::InfinitePlane(Vector3d const &origin, Vector3d const &normal, std::shared_ptr<Shader> const &shader)
: Primitive(shader), origin(origin), normal(normal)
{}
: Primitive(shader), origin(origin), normal(normal) {}
// Primitive functions /////////////////////////////////////////////////////////
bool InfinitePlane::intersect(Ray &ray) const
{
float directionDotNormal = dotProduct(ray.direction, this->normal);
bool InfinitePlane::intersect(Ray &ray) const {
float const cosine = dotProduct(ray.direction, this->normal);
// Make sure the ray is not coming from the other side (backface culling).
// Note: We only use backface culling for InfinitePlanes, because we have
// some special features planned that rely on backfaces for other primitives.
// Make sure the ray is not coming from the other side (backface culling).
// Note: We only use backface culling for InfinitePlanes, because we have
// some special features planned that rely on backfaces for other primitives.
if (cosine > 0)
return false;
/**
* If the dot product is 0, the ray is orthogonal to the normal => parallel to the plane => no intersection.
* If the dot product is negative, the ray is coming from the wrong side.
*/
if (directionDotNormal <= 0)
{
return false;
}
// Determine the distance at which the ray intersects the plane
float const t = dotProduct(this->origin - ray.origin, this->normal) / cosine;
// Basic formular to calculate intersection between ray and plane
float t = (length(this->origin) - dotProduct(ray.origin,this->normal)) / directionDotNormal;
// Test whether this is the foremost primitive in front of the camera
if (t < EPSILON || ray.length < t)
return false;
// If t negative, collision happens behind the camera
if (t < 0)
{
return false;
}
// Set the normal
// IMPLEMENT ME
// Test whether this is the foremost primitive in front of the camera
if (t >= ray.length)
{
// Is bigger, so further away
return false;
}
// Set the new length and the current primitive
ray.length = t;
ray.primitive = this;
// (Optional for now) Set the normal
ray.normal = this->normal;
// Set the new length and the current primitive
ray.primitive = this;
ray.length = t;
return true;
// True, because the primitive was hit
return true;
}
// Bounding box ////////////////////////////////////////////////////////////////
float InfinitePlane::minimumBounds(int dimension) const
{
if (this->normal[dimension] == 1.0f) // plane is orthogonal to the axis
return this->origin[dimension] - EPSILON;
else
return -INFINITY;
float InfinitePlane::minimumBounds(int dimension) const {
if (this->normal[dimension] == 1.0f) // plane is orthogonal to the axis
return this->origin[dimension] - EPSILON;
else
return -INFINITY;
}
float InfinitePlane::maximumBounds(int dimension) const
{
if (this->normal[dimension] == 1.0f) // plane is orthogonal to the axis
return this->origin[dimension] + EPSILON;
else
return +INFINITY;
float InfinitePlane::maximumBounds(int dimension) const {
if (this->normal[dimension] == 1.0f) // plane is orthogonal to the axis
return this->origin[dimension] + EPSILON;
else
return +INFINITY;
}

View file

@ -1,6 +1,5 @@
#include "common/ray.h"
#include "primitive/sphere.h"
#include <cmath>
// Constructor /////////////////////////////////////////////////////////////////
@ -12,69 +11,45 @@ Sphere::Sphere(Vector3d const &center, float radius, std::shared_ptr<Shader> con
// Primitive functions /////////////////////////////////////////////////////////
bool Sphere::intersect(Ray &ray) const {
auto origin = ray.origin - this->center;
// Use the definitions from the lecture
Vector3d const difference = ray.origin - this->center;
float const a = 1.0f;
float const b = 2.0f * dotProduct(ray.direction, difference);
float const c = dotProduct(difference, difference) - this->radius * this->radius;
float const discriminant = b * b - 4 * a * c;
// Determine whether the ray intersects the sphere
float A = pow(ray.direction[Vector3d::Dimension::X], 2) +
pow(ray.direction[Vector3d::Dimension::Y], 2) +
pow(ray.direction[Vector3d::Dimension::Z], 2);
float B = 2 * (
ray.direction[Vector3d::Dimension::X] * origin[Vector3d::Dimension::X] +
ray.direction[Vector3d::Dimension::Y] * origin[Vector3d::Dimension::Y] +
ray.direction[Vector3d::Dimension::Z] * origin[Vector3d::Dimension::Z]
);
float C = pow(origin[Vector3d::Dimension::X], 2) +
pow(origin[Vector3d::Dimension::Y], 2) +
pow(origin[Vector3d::Dimension::Z], 2) -
pow(this->radius, 2);
// Test whether the ray could intersect at all
if (discriminant < 0)
return false;
float const root = std::sqrt(discriminant);
float t = INFINITY;
// Stable solution
float const q = -0.5f * (b < 0 ? (b - root) : (b + root));
float const t0 = q / a;
float const t1 = c / q;
float t = std::min(t0, t1);
if (t < EPSILON)
t = std::max(t0, t1);
float discriminant = B * B - 4 * A * C;
if (discriminant < 0) {
return false;
} else if (discriminant == 0) {
t = -B / (2 * A);
} else { // discriminant > 0
float q {static_cast<float>([B, discriminant](){
if (B < 0) {
return -0.5f * (B - sqrt(discriminant));
} else {
return -0.5f * (B + sqrt(discriminant));
}
}())};
float t0 = q / A;
float t1 = C / q;
if (t0 < 0 && t1 < 0) {
return false;
}
if (t0 < 0) {
t = t1;
} else if (t1 < 0) {
t = t0;
} else {
t = std::min(t0, t1);
}
}
// Test whether this is the foremost primitive in front of the camera
if (t < EPSILON || ray.length < t)
return false;
if (t >= ray.length) {
return false;
}
// (Optional for now) Calculate the normal
auto intersectPoint = ray.origin + ray.direction * t;
auto normalDirection = intersectPoint - this->center; // Point of intersect - origin of sphere creates a line along the normal, pointing outwards
ray.normal = normalized(normalDirection);
// (Optional for now) Calculate the surface position
// Calculate the normal
// IMPLEMENT ME
// Calculate the surface position and tangent vector
float const phi = std::acos(ray.normal.y);
float const rho = std::atan2(ray.normal.z, ray.normal.x) + PI;
ray.surface = Vector2d(rho / (2 * PI), phi / PI);
ray.tangent = Vector3d(std::sin(rho), 0, std::cos(rho));
ray.bitangent = normalized(crossProduct(ray.normal, ray.tangent));
// Set the new length and the current primitive
ray.length = t;
ray.primitive = this;
// True, because the primitive was hit
return true;
}

View file

@ -3,102 +3,118 @@
// Constructor /////////////////////////////////////////////////////////////////
Triangle::Triangle(std::shared_ptr<Shader> const &shader) : Primitive(shader)
{}
Triangle::Triangle(std::shared_ptr<Shader> const &shader) : Primitive(shader) {}
Triangle::Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, std::shared_ptr<Shader> const &shader)
: Primitive(shader), vertex{a, b, c}
{}
Triangle::Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, std::shared_ptr<Shader> const &shader) : Primitive(shader), vertex{a, b, c} {}
Triangle::Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb,
Vector3d const &nc, std::shared_ptr<Shader> const &shader)
: Primitive(shader), vertex{a, b, c}, normal{na, nb, nc}
{}
Triangle::Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb, Vector3d const &nc, std::shared_ptr<Shader> const &shader) : Primitive(shader), vertex{a, b, c}, normal{na, nb, nc} {}
Triangle::Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb,
Vector3d const &nc, Vector2d const &ta, Vector2d const &tb, Vector2d const &tc,
std::shared_ptr<Shader> const &shader)
: Primitive(shader), vertex{a, b, c}, normal{na, nb, nc}, surface{ta, tb, tc}
{}
Triangle::Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb, Vector3d const &nc, Vector2d const &ta, Vector2d const &tb, Vector2d const &tc, std::shared_ptr<Shader> const &shader)
: Primitive(shader), vertex{a, b, c}, normal{na, nb, nc}, surface{ta, tb, tc} {}
Triangle::Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb, Vector3d const &nc, Vector3d const &tana, Vector3d const &tanb, Vector3d const &tanc, Vector3d const &ba,
Vector3d const &bb, Vector3d const &bc, Vector2d const &ta, Vector2d const &tb, Vector2d const &tc, std::shared_ptr<Shader> const &shader)
: Primitive(shader), vertex{a, b, c}, normal{na, nb, nc}, tangent{tana, tanb, tanc}, bitangent{ba, bb, bc}, surface{ta, tb, tc} {}
// Primitive functions /////////////////////////////////////////////////////////
bool Triangle::intersect(Ray &ray) const
{
Vector3d edge1 = this->vertex[0] - this->vertex[2];
Vector3d edge2 = this->vertex[1] - this->vertex[2];
Vector3d normalVector = normalized(crossProduct(edge1, edge2));
float d = dotProduct(this->vertex[0], normalVector) / length(normalVector);
// catch divided by 0, in case the triangle plane is not hit
float dotDirectionNormalVector = dotProduct(ray.direction, normalVector);
if (dotDirectionNormalVector == 0)
{
return false;
bool Triangle::intersectArea(Ray &ray) const {
// alternative triangle test
// "signed" triangle area with respect to triangle normal
auto triangleArea = [](Vector3d const &v0, Vector3d const &v1, Vector3d const &v2, Vector3d const &normal = Vector3d(0, 0, 0)) {
if (length(normal) < EPSILON) {
return length(crossProduct(v2 - v0, v1 - v0)) / 2.0f;
} else {
Vector3d const cp = crossProduct(v2 - v0, v1 - v0);
return dotProduct(cp, normal) > 0.0f ? length(cp) / 2.0f : -length(cp) / 2.0f;
}
};
float t = (d - dotProduct(ray.origin, normalVector)) / dotDirectionNormalVector;
Vector3d p = ray.origin + t * ray.direction;
// begin ray-plane intersection ----------------------------
Vector3d normal = normalized(crossProduct(vertex[2] - vertex[0], vertex[1] - vertex[0]));
// Barycentric Coordinates a,b to determine if intersect with Triangle
float triangleArea = length(crossProduct(this->vertex[2] - this->vertex[0], this->vertex[1] - this->vertex[0])) / 2;
float const cosine = dotProduct(ray.direction, normal);
Vector3d rightSide = crossProduct(p - this->vertex[1], this->vertex[2] - this->vertex[1]);
Vector3d leftSide = crossProduct(p - this->vertex[2], this->vertex[0] - this->vertex[2]);
if (abs(cosine) < EPSILON)
return false;
float triangleAreaRightSide = length(rightSide) / 2;
float triangleAreaLeftSide = length(leftSide) / 2;
float const t = dotProduct(vertex[0] - ray.origin, normal) / cosine;
float a = triangleAreaRightSide / triangleArea;
if (t < EPSILON || ray.length < t)
return false;
float b = triangleAreaLeftSide / triangleArea;
Vector3d const p = ray.origin + t * ray.direction;
// end ray-plane intersection ----------------------------
// Determine whether the ray intersects the triangle
float const fullArea = triangleArea(vertex[0], vertex[1], vertex[2]);
float const a = triangleArea(p, vertex[0], vertex[1], normal) / fullArea;
float const b = triangleArea(p, vertex[2], vertex[0], normal) / fullArea;
if ((a < 0.0f) || (a > 1.0f) || (b < 0.0f) || (a + b > 1.0f))
return false;
if (a < 0 || a > 1 || b < 0 || a+b > 1)
{
return false;
}
// Set the surface position (barycentric coordinates) and tangent Vector
ray.surface = a * this->surface[1] + b * this->surface[2] + (1 - a - b) * this->surface[0];
if (dotProduct(normalVector, leftSide) > 0)
{
return false;
}
// Set the new length and the current primitive
ray.length = t;
ray.primitive = this;
if (dotProduct(normalVector, rightSide) > 0)
{
return false;
}
// True, because the primitive was hit
return true;
}
// Test whether this is the foremost primitive in front of the camera
if (t >= ray.length)
{
//it is bigger so further away
return false;
}
bool Triangle::intersect(Ray &ray) const {
// We use the MöllerTrumbore intersection algorithm
// (Optional for now) Calculate the normal
ray.normal = normalVector; // Should be the correct one, I assume
// Determine two neighboring edge vectors
Vector3d const edge1 = this->vertex[1] - this->vertex[0];
Vector3d const edge2 = this->vertex[2] - this->vertex[0];
// (Optional for now) Calculate the surface position
// Begin calculating determinant
Vector3d const pVec = crossProduct(ray.direction, edge2);
// Set the new length and the current primitive
ray.length = t;
ray.primitive = this;
// Make sure the ray is not parallel to the triangle
float const det = dotProduct(edge1, pVec);
if (fabs(det) < EPSILON)
return false;
float const inv_det = 1.0f / det;
return true;
// Calculate u and test bound
Vector3d const tVec = ray.origin - this->vertex[0];
float const u = dotProduct(tVec, pVec) * inv_det;
// Test whether the intersection lies outside the triangle
if (0.0f > u || u > 1.0f)
return false;
// Calculate v and test bound
Vector3d const qVec = crossProduct(tVec, edge1);
float const v = dotProduct(ray.direction, qVec) * inv_det;
// Test whether the intersection lies outside the triangle
if (0.0f > v || u + v > 1.0f)
return false;
// Test whether this is the foremost primitive in front of the camera
float const t = dotProduct(edge2, qVec) * inv_det;
if (t < EPSILON || ray.length < t)
return false;
// Calculate the normal
// IMPLEMENT ME
// Calculate the surface position
ray.surface = u * this->surface[1] + v * this->surface[2] + (1 - u - v) * this->surface[0];
// Set the new length and the current primitive
ray.length = t;
ray.primitive = this;
// True, because the primitive was hit
return true;
}
// Bounding box ////////////////////////////////////////////////////////////////
float Triangle::minimumBounds(int dimension) const
{
return std::min(this->vertex[0][dimension], std::min(this->vertex[1][dimension], this->vertex[2][dimension]));
}
float Triangle::minimumBounds(int dimension) const { return std::min(this->vertex[0][dimension], std::min(this->vertex[1][dimension], this->vertex[2][dimension])); }
float Triangle::maximumBounds(int dimension) const
{
return std::max(this->vertex[0][dimension], std::max(this->vertex[1][dimension], this->vertex[2][dimension]));
}
float Triangle::maximumBounds(int dimension) const { return std::max(this->vertex[0][dimension], std::max(this->vertex[1][dimension], this->vertex[2][dimension])); }

View file

@ -9,22 +9,28 @@ public:
// Constructor
Triangle(std::shared_ptr<Shader> const &shader);
Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, std::shared_ptr<Shader> const &shader);
Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb,
Vector3d const &nc, std::shared_ptr<Shader> const &shader);
Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb,
Vector3d const &nc, Vector2d const &ta, Vector2d const &tb, Vector2d const &tc,
std::shared_ptr<Shader> const &shader);
Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb, Vector3d const &nc, std::shared_ptr<Shader> const &shader);
Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb, Vector3d const &nc, Vector2d const &ta, Vector2d const &tb, Vector2d const &tc, std::shared_ptr<Shader> const &shader);
Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb, Vector3d const &nc, Vector3d const &tana, Vector3d const &tanb, Vector3d const &tanc, Vector3d const &ba, Vector3d const &bb,
Vector3d const &bc, Vector2d const &ta, Vector2d const &tb, Vector2d const &tc, std::shared_ptr<Shader> const &shader);
// Set
void setVertex(int index, Vector3d const &vertex) { this->vertex[index] = vertex; }
void setNormal(int index, Vector3d const &normal) { this->normal[index] = normalized(normal); }
Vector3d getNormal(int index){return this->normal[index];}
void setTangent(int index, Vector3d const &tangent) { this->tangent[index] = normalized(tangent); }
void setBitangent(int index, Vector3d const &bitangent) { this->bitangent[index] = normalized(bitangent); }
void setSurface(int index, Vector2d const &surface) { this->surface[index] = surface; }
// Get
Vector3d getPosition(size_t index) { return this->vertex[index]; }
Vector3d getNormal(size_t index) { return this->normal[index]; }
Vector3d getTangent(size_t index) { return this->tangent[index]; }
Vector3d getBitangent(size_t index) { return this->bitangent[index]; }
Vector2d getTexCoord(size_t index) { return this->surface[index]; }
// Primitive functions
bool intersect(Ray &ray) const override;
bool intersectArea(Ray &ray) const;
// Bounding box
float minimumBounds(int dimension) const override;

View file

@ -8,18 +8,54 @@
Texture SimpleRenderer::renderImage(Scene const &scene, Camera const &camera, int width, int height) {
Texture image(width, height);
// Calculate the aspect ratio
float max_x = std::min(1.0f, static_cast<float>(width) / height);
float max_y = std::min(1.0f, static_cast<float>(height) / width);
// Setup timer
std::chrono::steady_clock::time_point start, stop;
// Create the image by casting one ray into the scene for each pixel
float pixel_step_x = 2 * max_x / width;
float pixel_step_y = 2 * max_y / height;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
Ray ray = camera.createRay((x - width/2) * pixel_step_x, (y - height/2) * pixel_step_y);
image.setPixelAt(x, height - 1 - y, scene.traceRay(ray));
// Reset Ray counting
Ray::resetRayCount();
// Super-hacky progress bar!
std::cout << "(SimpleRenderer): Begin rendering..." << std::endl;
std::cout << "| 0%";
int const barSize = 50;
int const stepSize = (width * height) / barSize;
for (int i = 0; i < barSize - 3 - 5; ++i)
std::cout << " ";
std::cout << "100% |" << std::endl << "|";
int k = 0;
// Start timer
start = std::chrono::steady_clock::now();
float const aspectRatio = static_cast<float>(height) / width;
for (int x = 0; x < image.width(); ++x) {
for (int y = 0; y < image.height(); ++y) {
Ray ray = camera.createRay((static_cast<float>(x) / width * 2 - 1), -(static_cast<float>(y) / height * 2 - 1) * aspectRatio);
image.setPixelAt(x, y, clamped(scene.traceRay(ray)));
// Super hacky progress bar!
if (++k % stepSize == 0) {
std::cout << "=" << std::flush;
}
}
}
// Stop timer
stop = std::chrono::steady_clock::now();
std::cout << "| Done!" << std::endl;
// Calculate the Time taken in seconds
double seconds = std::chrono::duration_cast<std::chrono::duration<double>>(stop - start).count();
std::cout << "Time: " << seconds << "s" << std::endl;
// Get the number of seconds per ray
int rays = Ray::getRayCount();
std::cout << "Paths: " << rays << std::endl;
std::cout << "Paths per second: " << std::fixed << std::setprecision(0) << rays / seconds << std::endl;
return image;
}

View file

@ -9,6 +9,19 @@
#include <sstream>
#include <string>
const std::string WHITESPACE = " \n\r\t\f\v";
std::string ltrim(const std::string &s) {
size_t start = s.find_first_not_of(WHITESPACE);
return (start == std::string::npos) ? "" : s.substr(start);
}
std::string rtrim(const std::string &s) {
size_t end = s.find_last_not_of(WHITESPACE);
return (end == std::string::npos) ? "" : s.substr(0, end + 1);
}
std::string trim(const std::string &s) { return rtrim(ltrim(s)); }
void Scene::add(const std::shared_ptr<Light> &light) { this->lights_.push_back(light); }
void Scene::add(const std::shared_ptr<Primitive> &primitive) {

View file

@ -11,7 +11,6 @@
// Forward declarations
class Light;
class Primitive;
class Shader;
class Scene {

View file

@ -3,11 +3,10 @@
MirrorShader::MirrorShader() {}
Color MirrorShader::shade(Scene const &scene, Ray const &ray) const
{
// IMPLEMENT ME
// Calculate the reflection vector
// Create a new reflection ray
// Send the new ray out into the scene and return the result
return Color(0, 0, 1);
Color MirrorShader::shade(Scene const &scene, Ray const &ray) const {
// IMPLEMENT ME
// Calculate the reflection vector
// Create a new reflection ray
// Send the new ray out into the scene and return the result
return Color(0, 0, 1);
}

View file

@ -3,15 +3,14 @@
#include "shader/shader.h"
class MirrorShader : public Shader
{
class MirrorShader : public Shader {
public:
// Constructor
MirrorShader();
// Constructor
MirrorShader();
// Shader functions
Color shade(Scene const &scene, Ray const &ray) const override;
// Shader functions
Color shade(Scene const &scene, Ray const &ray) const override;
};
#endif

View file

@ -3,14 +3,13 @@
RefractionShader::RefractionShader(float indexInside, float indexOutside) : indexInside(indexInside), indexOutside(indexOutside) {}
Color RefractionShader::shade(Scene const &scene, Ray const &ray) const
{
// IMPLEMENT ME
// Calculate the refracted ray using the surface normal vector and
// indexInside, indexOutside
// Also check for total internal reflection
// Send out a new refracted ray into the scene; recursively call traceRay()
return Color(1, 0, 0);
Color RefractionShader::shade(Scene const &scene, Ray const &ray) const {
// IMPLEMENT ME
// Calculate the refracted ray using the surface normal vector and
// indexInside, indexOutside
// Also check for total internal reflection
// Send out a new refracted ray into the scene; recursively call traceRay()
return Color(1, 0, 0);
}
bool RefractionShader::isTransparent() const { return true; }

View file

@ -3,20 +3,19 @@
#include "shader/shader.h"
class RefractionShader : public Shader
{
class RefractionShader : public Shader {
public:
// Constructor
RefractionShader(float indexInside, float indexOutside);
// Constructor
RefractionShader(float indexInside, float indexOutside);
// Shader functions
Color shade(Scene const &scene, Ray const &ray) const override;
bool isTransparent() const override;
// Shader functions
Color shade(Scene const &scene, Ray const &ray) const override;
bool isTransparent() const override;
private:
float indexInside;
float indexOutside;
float indexInside;
float indexOutside;
};
#endif

View file

@ -4,10 +4,9 @@
SimpleShadowShader::SimpleShadowShader(Color const &objectColor) : objectColor(objectColor) {}
Color SimpleShadowShader::shade(Scene const &scene, Ray const &ray) const
{
// IMPLEMENT ME
// loop over all light sources to check for visibility and multiply "light
// strength" with this objects albedo (color)
return Color(0, 1, 0);
Color SimpleShadowShader::shade(Scene const &scene, Ray const &ray) const {
// IMPLEMENT ME
// loop over all light sources to check for visibility and multiply "light
// strength" with this objects albedo (color)
return Color(0, 1, 0);
}

View file

@ -3,18 +3,17 @@
#include "shader/shader.h"
class SimpleShadowShader : public Shader
{
class SimpleShadowShader : public Shader {
public:
// Constructor
SimpleShadowShader(Color const &objectColor);
// Constructor
SimpleShadowShader(Color const &objectColor);
// Shader functions
Color shade(Scene const &scene, Ray const &ray) const override;
// Shader functions
Color shade(Scene const &scene, Ray const &ray) const override;
private:
Color objectColor;
Color objectColor;
};
#endif