diff options
| Commit | 2a3a4296e747a5b15786646a1ec5142ad23331c2 (patch) | |
|---|---|---|
| Author | 2024-05-27 18:18:30 +0300 | |
| Committer | 2024-05-27 18:18:30 +0300 | |
| Files | 504bb49625e48c216fa2a7d28b5cbac4a2f6b31e | |
| uni-projects-2a3a4296e747a5b15786646a1ec5142ad23331c2.tar uni-projects-2a3a4296e747a5b15786646a1ec5142ad23331c2.tar.gz uni-projects-2a3a4296e747a5b15786646a1ec5142ad23331c2.zip | ||
| Parent | 1b7010f0a1095591bbe59b29908a6524af239a32 (diff) | |
[raytracing] Added solutions to raytracing exercises
3 files changed, 1033 insertions, 0 deletions
diff --git a/Year 3/Raytracing/0004-h9-Added-Wireframe-shader.patch b/Year 3/Raytracing/0004-h9-Added-Wireframe-shader.patch new file mode 100644 index 0000000..8c0d3f7 --- /dev/null +++ b/Year 3/Raytracing/0004-h9-Added-Wireframe-shader.patch @@ -0,0 +1,649 @@ +From f9cb883ef657806c5de5d5268856f740c151ff69 Mon Sep 17 00:00:00 2001 +From: Syndamia <kamen@syndamia.com> +Date: Sun, 26 May 2024 14:42:39 +0300 +Subject: [PATCH] [h9] Added Wireframe shader + +--- + data/hw9/dragon.hexray | 86 ++++++++++++++++++++++ + data/hw9/nonconvex.hexray | 119 ++++++++++++++++++++++++++++++ + data/hw9/testmesh.hexray | 150 ++++++++++++++++++++++++++++++++++++++ + data/hw9/wireframe.hexray | 72 ++++++++++++++++++ + flake.lock | 27 +++++++ + flake.nix | 26 +++++++ + src/geometry.h | 4 +- + src/main.cpp | 2 +- + src/mesh.cpp | 2 + + src/scene.cpp | 1 + + src/shading.cpp | 8 ++ + src/shading.h | 20 +++++ + 12 files changed, 515 insertions(+), 2 deletions(-) + create mode 100644 data/hw9/dragon.hexray + create mode 100644 data/hw9/nonconvex.hexray + create mode 100644 data/hw9/testmesh.hexray + create mode 100644 data/hw9/wireframe.hexray + create mode 100644 flake.lock + create mode 100644 flake.nix + +diff --git a/data/hw9/dragon.hexray b/data/hw9/dragon.hexray +new file mode 100644 +index 0000000..ba924da +--- /dev/null ++++ b/data/hw9/dragon.hexray +@@ -0,0 +1,86 @@ ++// ++// A scene with a "heavy" mesh (the stanford dragon) ++// ++// ++ ++// 1. First, some global settings ++GlobalSettings { ++ frameWidth 768 ++ frameHeight 512 ++ ambientLight (0.28, 0.30, 0.35) ++ lightPos (160, 80, 40) ++ lightIntensity 5000 ++} ++ ++// 2. A camera ++Camera camera { ++ pos (140, 23, 70) ++ yaw 66 ++ pitch -10 ++ roll 0.0 ++ fov 90 ++ aspectRatio 1.5 ++} ++ ++Plane floor { ++ y 0 ++ limit 128 ++} ++ ++CheckerTexture checker { ++ color1 (0.5, 0.5, 0.25) ++ color2 (0.25, 0.25, 0.25) ++ scaling 8 ++} ++ ++Lambert floorDiffuse { ++ color (1, 1, 1) ++ texture checker ++} ++ ++Reflection floorMirror { ++ reflColor (0.05, 0.03, 0.03) ++} ++ ++Reflection floorGlossy { ++ glossiness 0.50 ++ numSamples 25 ++ reflColor (0.06, 0.06, 0.10) ++} ++ ++Layered floorShader { ++ layer floorMirror (1, 1, 1) ++ layer floorGlossy (0.05, 0.05, 0.075) ++} ++ ++// 3. A floor node, using a plane as a geometry, and a flat shader with a checker texture ++Node floorNode { ++ geometry floor ++ shader floorGlossy ++ translate (100, 0, 96) ++} ++ ++Mesh dragon { ++ useKDTree true ++ file "dragon.obj" ++ useSAH off ++} ++ ++Phong white { ++ color (0.7, 0.7, 0.7) ++ exponent 133 ++} ++ ++Node dragonNode { ++ geometry dragon ++ shader white ++ translate (104, 13.44, 93) ++ rotate (90, 90, 0) ++ scale (30, 30, 30) ++} ++ ++ ++// 5. The cubemap environment: ++CubemapEnvironment environment { ++ folder "../env/forest" ++} +diff --git a/data/hw9/nonconvex.hexray b/data/hw9/nonconvex.hexray +new file mode 100644 +index 0000000..bb609ac +--- /dev/null ++++ b/data/hw9/nonconvex.hexray +@@ -0,0 +1,119 @@ ++// ++// Sample scene with non-convex geometries ++// ++ ++GlobalSettings { ++ frameWidth 640 ++ frameHeight 480 ++ ambientLight (0, 0, 0) ++ lightPos (-30, 100, -250) ++ lightIntensity 50000 ++ ++} ++ ++Camera camera { ++ pos (0, 50, -50) ++ //pos (0, 100, -100) ++ aspectRatio 1.33333 ++ yaw 0 ++ pitch -30 ++ roll 0 ++ fov 90 ++} ++ ++Plane floor { ++ y 2 ++} ++ ++CheckerTexture checker { ++ color1 (0, 0, 0) ++ color2 (0, 0.5, 1) ++ size 5 ++} ++ ++Lambert floor_shader { ++ texture checker ++} ++ ++Node floor { ++ geometry floor ++ shader floor_shader ++} ++ ++ ++Mesh 1 { ++ file "fig1.obj" ++ faceted true ++} ++ ++Lambert L1 { ++ color (0.6, 0.5, 0.5) ++} ++ ++Node 1 { ++ geometry 1 ++ shader L1 ++ scale (10, 10, 10) ++} ++ ++/* ++Mesh 2 { ++ file "fig2.obj" ++ faceted true ++} ++ ++Lambert L2 { ++ color (0.5, 0.7, 0.5) ++} ++ ++Node 2 { ++ geometry 2 ++ shader L2 ++ scale (10, 10, 10) ++} ++ ++Mesh 3 { ++ file "fig3.obj" ++ faceted true ++} ++ ++Lambert L3 { ++ color (0.5, 0.5, 0.7) ++} ++ ++Node 3 { ++ geometry 3 ++ shader L3 ++ scale (10, 10, 10) ++} ++ ++Mesh 4 { ++ file "fig4.obj" ++ faceted true ++} ++ ++Lambert L4 { ++ color (0.7, 0.5, 0.5) ++} ++ ++Node 4 { ++ geometry 4 ++ shader L4 ++ scale (10, 10, 10) ++} ++ ++Mesh 5 { ++ file "fig5.obj" ++ faceted true ++} ++ ++Lambert L5 { ++ color (0.5, 0.7, 0.7) ++} ++ ++Node 5 { ++ geometry 5 ++ shader L5 ++ scale (10, 10, 10) ++} ++*/ +diff --git a/data/hw9/testmesh.hexray b/data/hw9/testmesh.hexray +new file mode 100644 +index 0000000..3ef4847 +--- /dev/null ++++ b/data/hw9/testmesh.hexray +@@ -0,0 +1,150 @@ ++// ++// An example scene, which represents the same scenery as what the initializeScene() ++// function used to create around the tag 'homework6' ++// Namely: ++// 1) A shiny floor, made of a woody Lambert shader and a mirror layer on top ++// 2) A soccer ball ++// 3) A shiny ball using a glossy shader ++// 4) Three small phong-lit balls, using red, yellow and green colors ++ ++// 1. First, some global settings ++GlobalSettings { ++ frameWidth 640 ++ frameHeight 480 ++ ambientLight (0.08, 0.08, 0.08) ++ lightPos (-750, 1200, -750) ++ lightIntensity 1200000 ++} ++ ++// 2. A camera ++Camera camera { ++ pos (90, 160, -320) ++ aspectRatio 1.33333 ++ yaw 15 ++ pitch -5 ++ roll 0 ++ fov 75 ++// focalPlaneDist 300 ++// fNumber 2.0 ++// dof false ++// numSamples 100 ++} ++ ++// 3. The floor node: ++Plane floor { ++ y -0.01 ++ limit 200 ++} ++ ++BitmapTexture wood_tex { ++ file "../texture/wood.bmp" ++ scaling 400 ++} ++ ++Lambert floor_diffuse { ++ texture wood_tex ++} ++ ++Reflection mirror { ++} ++ ++Fresnel mirror_fresnel { ++ ior 1.33 ++} ++ ++Layered floor_shader { ++ layer floor_diffuse (1, 1, 1) ++ layer mirror (1, 1, 1) mirror_fresnel ++} ++ ++Node floor { ++ geometry floor ++ shader floor_shader ++} ++ ++Reflection refl { ++} ++ ++Refraction refr { ++ ior 1.6 ++} ++ ++Fresnel fresnel { ++ ior 1.6 ++} ++ ++Layered glass { ++ layer refr (1, 1, 1) ++ layer refl (1, 1, 1) fresnel ++} ++ ++// 4. The mesh: ++Mesh mesh { ++// file "geom/3pyramid.obj" ++// file "geom/teapot_lowres.obj" ++// file "geom/heart.obj" ++ file "../geom/newwine.obj" ++// file "geom/truncated_cube.obj" ++// backfaceCulling false ++ faceted false ++} ++ ++CheckerTexture checker { ++ color1 (0.70, 0.70, 0.70) ++ color2 (0.15, 0.15, 0.15) ++ scaling 100 ++} ++ ++Lambert checker_shader { ++ texture checker ++} ++ ++BitmapTexture heart_lava { ++ file "../texture/zar-texture.bmp" ++} ++ ++Lambert heart_shader { ++ texture heart_lava ++} ++ ++Reflection reflection { ++} ++ ++Refraction refraction { ++ ior 1.5 ++} ++ ++Fresnel fresnel { ++ ior 1.5 ++} ++ ++Layered glass { ++ layer refraction (1, 1, 1) ++ layer reflection (1, 1, 1) fresnel ++} ++ ++CheckerTexture checker1 { ++ color1 (0.2, 0.2, 0.2) ++ color2 (0.8, 0.8, 0.8) ++ scaling 10 ++} ++ ++Lambert lambert { ++ color (0.7, 0.7, 0.7) ++ texture checker ++} ++ ++Node soccer_ball { ++ geometry mesh ++ shader glass ++ scale (230, 230, 230) ++ rotate (135, 0, 0) ++ translate (0, 0, 0) ++// bump bumptex ++} ++ ++ ++// 7. And, finally, an environment ++CubemapEnvironment { ++ folder "../env/forest" ++} +diff --git a/data/hw9/wireframe.hexray b/data/hw9/wireframe.hexray +new file mode 100644 +index 0000000..0f0a54b +--- /dev/null ++++ b/data/hw9/wireframe.hexray +@@ -0,0 +1,72 @@ ++// ++// A sample scene for the homeworks for Lecture 9 ++// ++ ++// 1. First, some global settings ++GlobalSettings { ++ frameWidth 640 ++ frameHeight 480 ++ ambientLight (0.28, 0.30, 0.35) ++ lightPos (160, 80, 33) ++ lightIntensity 10000 ++} ++ ++// 2. A camera ++Camera camera { ++ pos (120, 33, 40) ++ yaw 10 ++ pitch -15 ++ roll 0.0 ++ fov 90 ++ aspectRatio 1.333 ++} ++ ++Plane floor { ++ y 0 ++ limit 128 ++} ++ ++CheckerTexture checker { ++ color1 (0.5, 0.5, 0.25) ++ color2 (0.25, 0.25, 0.25) ++ scaling 8 ++} ++ ++Lambert floorShader { ++ color (1, 1, 1) ++ texture checker ++} ++ ++// 3. A floor node, using a plane as a geometry, and a flat shader with a checker texture ++Node floorNode { ++ geometry floor ++ shader floorShader ++ translate (100, 0, 96) ++} ++ ++Mesh heart { ++ file "../geom/heart.obj" ++} ++ ++Lambert white_flat { ++ color (0.7, 0.7, 0.7) ++} ++ ++Wireframe wireframe { ++ wireSize 0.08 ++ wireColor (0, 1, 0) ++ outColor (0, 0, 0) ++} ++ ++Node heartNode { ++ geometry heart ++ shader wireframe ++ translate (100, 12.1, 80) ++ rotate (120, 0, 0) ++ scale (6, 6, 6) ++} ++ ++// 5. The cubemap environment: ++CubemapEnvironment environment { ++ folder "../env/forest" ++} +diff --git a/flake.lock b/flake.lock +new file mode 100644 +index 0000000..25db693 +--- /dev/null ++++ b/flake.lock +@@ -0,0 +1,27 @@ ++{ ++ "nodes": { ++ "nixpkgs": { ++ "locked": { ++ "lastModified": 1716061101, ++ "narHash": "sha256-H0eCta7ahEgloGIwE/ihkyGstOGu+kQwAiHvwVoXaA0=", ++ "owner": "nixos", ++ "repo": "nixpkgs", ++ "rev": "e7cc61784ddf51c81487637b3031a6dd2d6673a2", ++ "type": "github" ++ }, ++ "original": { ++ "owner": "nixos", ++ "ref": "nixos-23.11", ++ "repo": "nixpkgs", ++ "type": "github" ++ } ++ }, ++ "root": { ++ "inputs": { ++ "nixpkgs": "nixpkgs" ++ } ++ } ++ }, ++ "root": "root", ++ "version": 7 ++} +diff --git a/flake.nix b/flake.nix +new file mode 100644 +index 0000000..d0a99fd +--- /dev/null ++++ b/flake.nix +@@ -0,0 +1,26 @@ ++# Този файл, заедно с flake.lock са си за моета система, да имам копие ако случайно изтрия нещо ++{ ++ description = "hexray raytracer in FMI elective"; ++ ++ inputs = { ++ nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11"; ++ }; ++ ++ outputs = inputs: ++ let ++ pkgs = inputs.nixpkgs.legacyPackages."x86_64-linux"; ++ in { ++ devShells."x86_64-linux".default = pkgs.mkShell { ++ nativeBuildInputs = with pkgs; [ ++ cmake ++ pkg-config ++ ]; ++ ++ buildInputs = with pkgs; [ ++ SDL2 ++ openexr_3 ++ zlib ++ ]; ++ }; ++ }; ++} +diff --git a/src/geometry.h b/src/geometry.h +index 4af6360..e7b4a8c 100644 +--- a/src/geometry.h ++++ b/src/geometry.h +@@ -37,6 +37,8 @@ struct IntersectionInfo { + Vector dNdx, dNdy; + double u, v; + Geometry *geom; ++ double lambda2; ++ double lambda3; + }; + + /** +@@ -133,4 +135,4 @@ public: + class CSGDiff: public CSGBase { // A - B + public: + virtual bool inside(bool inA, bool inB) override { return inA && !inB; } +-}; +\ No newline at end of file ++}; +diff --git a/src/main.cpp b/src/main.cpp +index 780804c..93a18ea 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -183,7 +183,7 @@ bool renderStatic() + return render(true); + } + +-const char* DEFAULT_SCENE = "data/heightfield.hexray"; ++const char* DEFAULT_SCENE = "data/hw9/wireframe.hexray"; + + int main(int argc, char** argv) + { +diff --git a/src/mesh.cpp b/src/mesh.cpp +index 2f6da05..86a6b0b 100644 +--- a/src/mesh.cpp ++++ b/src/mesh.cpp +@@ -160,8 +160,10 @@ bool Mesh::intersectTriangle(const Ray& ray, const Triangle& t, IntersectionInfo + double rDcr = 1/Dcr; + double lambda2 = det(H, AC, -ray.dir) * rDcr; + if (lambda2 < 0 || lambda2 > 1) return false; ++ info.lambda2 = lambda2; + double lambda3 = det(AB, H, -ray.dir) * rDcr; + if (lambda3 < 0 || lambda3 > 1) return false; ++ info.lambda3 = lambda3; + double lambda1 = 1 - (lambda2 + lambda3); + if (lambda1 < 0 || lambda1 > 1) return false; + double gamma = det(AB, AC, H) * rDcr; +diff --git a/src/scene.cpp b/src/scene.cpp +index 149320e..5ac4633 100644 +--- a/src/scene.cpp ++++ b/src/scene.cpp +@@ -804,6 +804,7 @@ SceneElement* DefaultSceneParser::newSceneElement(const char* className) + if (!strcmp(className, "Heightfield")) return new Heightfield; + if (!strcmp(className, "BumpTexture")) return new BumpTexture; + if (!strcmp(className, "Bumps")) return new Bumps; ++ if (!strcmp(className, "Wireframe")) return new Wireframe; + if (!strcmp(className, "Const")) return new Const; + + return NULL; +diff --git a/src/shading.cpp b/src/shading.cpp +index 25f3c80..f4d3f0a 100644 +--- a/src/shading.cpp ++++ b/src/shading.cpp +@@ -270,3 +270,11 @@ void Bumps::modifyNormal(IntersectionInfo& data) + data.norm.normalize(); + } + } ++ ++Color Wireframe::computeColor(Ray ray, const IntersectionInfo& info) { ++ double lambda1 = 1.0 - info.lambda2 - info.lambda3; ++ if (lambda1 < wireSize || info.lambda2 < wireSize || info.lambda3 < wireSize) { ++ return wireColor; ++ } ++ return outColor; ++} +diff --git a/src/shading.h b/src/shading.h +index 95e26c5..5a77b71 100644 +--- a/src/shading.h ++++ b/src/shading.h +@@ -199,3 +199,23 @@ public: + } + + }; ++ ++class Wireframe : public Shader { ++public: ++ double wireSize = 0.08; ++ Color wireColor = Color(0, 1, 0); ++ Color outColor = Color(0, 0, 0); ++ Wireframe(double wireSize = 0.08, ++ Color wireColor = Color(0, 1, 0), ++ Color outColor = Color(0, 0, 0)) : ++ wireSize(wireSize), wireColor(wireColor), outColor(outColor) ++ {} ++ Color computeColor(Ray ray, const IntersectionInfo& info) override; ++ ++ void fillProperties(ParsedBlock& pb) override ++ { ++ pb.getDoubleProp("wireSize", &wireSize); ++ pb.getColorProp("wireColor", &wireColor); ++ pb.getColorProp("outColor", &outColor); ++ } ++}; +-- +2.42.0 + diff --git a/Year 3/Raytracing/0005-h10-Implemented-SpotLight.patch b/Year 3/Raytracing/0005-h10-Implemented-SpotLight.patch new file mode 100644 index 0000000..f1fbfd6 --- /dev/null +++ b/Year 3/Raytracing/0005-h10-Implemented-SpotLight.patch @@ -0,0 +1,223 @@ +From 7b19946dab9bc0399214a36dc9067f56c4e0d3a8 Mon Sep 17 00:00:00 2001 +From: Syndamia <kamen@syndamia.com> +Date: Mon, 27 May 2024 09:22:23 +0300 +Subject: [PATCH] [h10] Implemented SpotLight + +--- + data/boxed.hexray | 37 ++++++++++++++++++------------------- + flake.lock | 27 +++++++++++++++++++++++++++ + flake.nix | 26 ++++++++++++++++++++++++++ + src/lights.cpp | 17 +++++++++++++++++ + src/lights.h | 19 +++++++++++++++++++ + src/main.cpp | 2 +- + src/scene.cpp | 1 + + src/vector.h | 4 ++++ + 8 files changed, 113 insertions(+), 20 deletions(-) + create mode 100644 flake.lock + create mode 100644 flake.nix + +diff --git a/data/boxed.hexray b/data/boxed.hexray +index e128db3..9ed1793 100644 +--- a/data/boxed.hexray ++++ b/data/boxed.hexray +@@ -18,25 +18,24 @@ Camera camera { + //////////////////////// LIGHTS //////////////////////////////////////////// + + +-RectLight l2 { +- xSubd 4 +- ySubd 4 +- translate (50, 50, -20) +- scale (8, 8, 8) +- color (1, 1, 1) +- power 4000 +- rotate (0, 45, 0) +-} +- +-RectLight l_small { +- translate (0, 28, 50) +- rotate (0, -62, 0) +- scale (10, 10, 10) +- color (1, 1, 1) +- power 4000 +- xSubd 4 +- ySubd 4 +-} ++SpotLight mylight { ++ color (1, 1, 1) ++ power 7000 ++ pos (50, 50, -20) ++ dir (-0.727, -0.582, 0.364) ++ innerAngle 13.8 ++ outerAngle 15.5 ++} ++ ++// RectLight l_small { ++// translate (0, 28, 50) ++// rotate (0, -62, 0) ++// scale (10, 10, 10) ++// color (1, 1, 1) ++// power 4000 ++// xSubd 4 ++// ySubd 4 ++// } + + + //////////////////////// GEOMETRIES //////////////////////////////////////// +diff --git a/flake.lock b/flake.lock +new file mode 100644 +index 0000000..25db693 +--- /dev/null ++++ b/flake.lock +@@ -0,0 +1,27 @@ ++{ ++ "nodes": { ++ "nixpkgs": { ++ "locked": { ++ "lastModified": 1716061101, ++ "narHash": "sha256-H0eCta7ahEgloGIwE/ihkyGstOGu+kQwAiHvwVoXaA0=", ++ "owner": "nixos", ++ "repo": "nixpkgs", ++ "rev": "e7cc61784ddf51c81487637b3031a6dd2d6673a2", ++ "type": "github" ++ }, ++ "original": { ++ "owner": "nixos", ++ "ref": "nixos-23.11", ++ "repo": "nixpkgs", ++ "type": "github" ++ } ++ }, ++ "root": { ++ "inputs": { ++ "nixpkgs": "nixpkgs" ++ } ++ } ++ }, ++ "root": "root", ++ "version": 7 ++} +diff --git a/flake.nix b/flake.nix +new file mode 100644 +index 0000000..d0a99fd +--- /dev/null ++++ b/flake.nix +@@ -0,0 +1,26 @@ ++# Този файл, заедно с flake.lock са си за моета система, да имам копие ако случайно изтрия нещо ++{ ++ description = "hexray raytracer in FMI elective"; ++ ++ inputs = { ++ nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11"; ++ }; ++ ++ outputs = inputs: ++ let ++ pkgs = inputs.nixpkgs.legacyPackages."x86_64-linux"; ++ in { ++ devShells."x86_64-linux".default = pkgs.mkShell { ++ nativeBuildInputs = with pkgs; [ ++ cmake ++ pkg-config ++ ]; ++ ++ buildInputs = with pkgs; [ ++ SDL2 ++ openexr_3 ++ zlib ++ ]; ++ }; ++ }; ++} +diff --git a/src/lights.cpp b/src/lights.cpp +index d1b5a42..f1e6406 100644 +--- a/src/lights.cpp ++++ b/src/lights.cpp +@@ -44,3 +44,20 @@ void RectLight::getNthSample(int sampleIdx, const Vector& shadePos, Vector& samp + color.makeZero(); + } + } ++ ++void SpotLight::getNthSample(int sampleIdx, const Vector& shadePos, Vector& samplePos, Color& color) { ++ samplePos = pos; ++ ++ Vector shadeDir = shadePos - pos; ++ double degr = degreesBetween(shadeDir, dir); ++ if (degr < innerAngle) { ++ color = this->color; ++ } ++ else if (degr > outerAngle) { ++ color = Color(0, 0, 0); ++ } ++ else { ++ double alpha = (degr - innerAngle) / (outerAngle - innerAngle); ++ color = (1 - alpha) * this->color + alpha * Color(0, 0, 0); ++ } ++} +diff --git a/src/lights.h b/src/lights.h +index 548b53f..c76b9be 100644 +--- a/src/lights.h ++++ b/src/lights.h +@@ -79,3 +79,22 @@ public: + void getNthSample(int sampleIdx, const Vector& shadePos, Vector& samplePos, Color& color) override; + }; + ++ ++class SpotLight : public Light { ++ Vector pos; ++ Vector dir; ++ double innerAngle; ++ double outerAngle; ++public: ++ void fillProperties(ParsedBlock& pb) override ++ { ++ Light::fillProperties(pb); ++ pb.getVectorProp("pos", &pos); ++ pb.getVectorProp("dir", &dir); ++ pb.getDoubleProp("innerAngle", &innerAngle); ++ pb.getDoubleProp("outerAngle", &outerAngle); ++ } ++ ++ int getNumSamples() const override { return 1; } ++ void getNthSample(int sampleIdx, const Vector& shadePos, Vector& samplePos, Color& color) override; ++}; +diff --git a/src/main.cpp b/src/main.cpp +index d523f60..7a181cb 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -222,7 +222,7 @@ bool renderStatic() + return render(true); + } + +-const char* DEFAULT_SCENE = "data/meshes.hexray"; ++const char* DEFAULT_SCENE = "data/boxed.hexray"; + + int main(int argc, char** argv) + { +diff --git a/src/scene.cpp b/src/scene.cpp +index f5fbdb0..82c8d98 100644 +--- a/src/scene.cpp ++++ b/src/scene.cpp +@@ -799,6 +799,7 @@ SceneElement* DefaultSceneParser::newSceneElement(const char* className) + if (!strcmp(className, "Const")) return new Const; + if (!strcmp(className, "PointLight")) return new PointLight; + if (!strcmp(className, "RectLight")) return new RectLight; ++ if (!strcmp(className, "SpotLight")) return new SpotLight; + + return NULL; + } +diff --git a/src/vector.h b/src/vector.h +index a21b432..cd140fb 100644 +--- a/src/vector.h ++++ b/src/vector.h +@@ -199,3 +199,7 @@ inline std::pair<Vector, Vector> othonormedBasis(const Vector& v) + result.second = result.first ^ v; + return result; + } ++ ++inline double degreesBetween(const Vector& a, const Vector& b) { ++ return acos(dot(normalize(a), normalize(b))) * 180 / M_PI; ++} +-- +2.42.0 + diff --git a/Year 3/Raytracing/0006-h12-Implemented-Russian-roulette-raytracing.patch b/Year 3/Raytracing/0006-h12-Implemented-Russian-roulette-raytracing.patch new file mode 100644 index 0000000..32372da --- /dev/null +++ b/Year 3/Raytracing/0006-h12-Implemented-Russian-roulette-raytracing.patch @@ -0,0 +1,161 @@ +From 6cf50cd269931e95f058e17c15dc210fc49fa216 Mon Sep 17 00:00:00 2001 +From: Syndamia <kamen@syndamia.com> +Date: Mon, 27 May 2024 17:46:57 +0300 +Subject: [PATCH] [h12] Implemented Russian-roulette raytracing + +--- + data/smallpt.hexray | 1 + + flake.lock | 27 +++++++++++++++++++++++++++ + flake.nix | 26 ++++++++++++++++++++++++++ + src/main.cpp | 14 ++++++++++++-- + src/scene.cpp | 1 + + src/scene.h | 3 +++ + 6 files changed, 70 insertions(+), 2 deletions(-) + create mode 100644 flake.lock + create mode 100644 flake.nix + +diff --git a/data/smallpt.hexray b/data/smallpt.hexray +index dfdc6e5..cdb0cf9 100644 +--- a/data/smallpt.hexray ++++ b/data/smallpt.hexray +@@ -11,6 +11,7 @@ GlobalSettings { + gi on + numPaths 40 + prepassSamples 300 ++ roulette on + } + + Camera camera { +diff --git a/flake.lock b/flake.lock +new file mode 100644 +index 0000000..25db693 +--- /dev/null ++++ b/flake.lock +@@ -0,0 +1,27 @@ ++{ ++ "nodes": { ++ "nixpkgs": { ++ "locked": { ++ "lastModified": 1716061101, ++ "narHash": "sha256-H0eCta7ahEgloGIwE/ihkyGstOGu+kQwAiHvwVoXaA0=", ++ "owner": "nixos", ++ "repo": "nixpkgs", ++ "rev": "e7cc61784ddf51c81487637b3031a6dd2d6673a2", ++ "type": "github" ++ }, ++ "original": { ++ "owner": "nixos", ++ "ref": "nixos-23.11", ++ "repo": "nixpkgs", ++ "type": "github" ++ } ++ }, ++ "root": { ++ "inputs": { ++ "nixpkgs": "nixpkgs" ++ } ++ } ++ }, ++ "root": "root", ++ "version": 7 ++} +diff --git a/flake.nix b/flake.nix +new file mode 100644 +index 0000000..d0a99fd +--- /dev/null ++++ b/flake.nix +@@ -0,0 +1,26 @@ ++# Този файл, заедно с flake.lock са си за моета система, да имам копие ако случайно изтрия нещо ++{ ++ description = "hexray raytracer in FMI elective"; ++ ++ inputs = { ++ nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11"; ++ }; ++ ++ outputs = inputs: ++ let ++ pkgs = inputs.nixpkgs.legacyPackages."x86_64-linux"; ++ in { ++ devShells."x86_64-linux".default = pkgs.mkShell { ++ nativeBuildInputs = with pkgs; [ ++ cmake ++ pkg-config ++ ]; ++ ++ buildInputs = with pkgs; [ ++ SDL2 ++ openexr_3 ++ zlib ++ ]; ++ }; ++ }; ++} +diff --git a/src/main.cpp b/src/main.cpp +index 5af773d..47c0028 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -115,6 +115,16 @@ Color pathtrace(Ray ray, Color pathMultiplier = Color(1, 1, 1)) + TraceContext tc; + auto earlyResult = tc.raycast(ray); + if (earlyResult) return (*earlyResult) * pathMultiplier; ++ ++ double rating = pathMultiplier.intensity(); ++ double rouletteContribution = 1.0; ++ if (scene.settings.roulette && ray.depth < 4 && rating < 1) { ++ double kill = randDouble(); ++ if (kill <= 1 - rating) { ++ return Color(0, 0, 0); ++ } ++ rouletteContribution = 1 / rating; ++ } + // Continue building the path: + // Option A: continue randomly + Ray newRay = ray; +@@ -123,7 +133,7 @@ Color pathtrace(Ray ray, Color pathMultiplier = Color(1, 1, 1)) + newRay.depth++; + tc.closestNode->shader->spawnRay(tc.closestIntersection, ray.dir, newRay, brdfColor, brdfPDF); + if (brdfPDF <= 0) return Color(0, 0, 0); +- Color fromGI = pathtrace(newRay, pathMultiplier * brdfColor / brdfPDF); ++ Color fromGI = pathtrace(newRay, pathMultiplier * brdfColor / brdfPDF) * rouletteContribution; + // + // Option B: explicit light sampling + // scheme: +@@ -160,7 +170,7 @@ Color pathtrace(Ray ray, Color pathMultiplier = Color(1, 1, 1)) + float pChooseLight = 1.0f / scene.lights.size(); + float pHitLight = 1.0f / solidAngle; + float pThisPath = pChooseLight * pHitLight; +- return fromGI + fromLight * pathMultiplier / pThisPath; ++ return fromGI + fromLight * pathMultiplier / pThisPath * rouletteContribution; + } + + bool visible(Vector A, Vector B) +diff --git a/src/scene.cpp b/src/scene.cpp +index c909d0c..69f9206 100644 +--- a/src/scene.cpp ++++ b/src/scene.cpp +@@ -772,6 +772,7 @@ void GlobalSettings::fillProperties(ParsedBlock& pb) + pb.getIntProp("prepassSamples", &prepassSamples, 0); + pb.getBoolProp("gi", &gi); + pb.getIntProp("numPaths", &numPaths, 1); ++ pb.getBoolProp("roulette", &roulette); + } + + SceneElement* DefaultSceneParser::newSceneElement(const char* className) +diff --git a/src/scene.h b/src/scene.h +index 250d561..327c828 100644 +--- a/src/scene.h ++++ b/src/scene.h +@@ -259,6 +259,9 @@ struct GlobalSettings: public SceneElement { + bool gi = false; + int numPaths = 32; + ++ // Russian roulette-related ++ bool roulette; ++ + void fillProperties(ParsedBlock& pb); + ElementType getElementType() const { return ELEM_SETTINGS; } + }; +-- +2.42.0 + |
