diff --git a/src/canvas.cpp b/src/canvas.cpp index efd5ec8..0898981 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1,4 +1,5 @@ #include "canvas.h" +#include #include v3 color::toV3(color c) @@ -61,3 +62,17 @@ void canvas::set(size_t x, size_t y, color c) data[p + 1] = c.g; data[p + 2] = c.b; } + +void canvas::savePPM(char * path) +{ + std::ofstream ofs; + ofs.open(path, std::ios::binary); + ofs << "P6\n" << width << " " << height << "\n255\n"; + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { + color c = get(x, y); + ofs << c.r << c.g << c.b; + } + } + ofs.close(); +} diff --git a/src/canvas.h b/src/canvas.h index 6d22963..468b008 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -16,6 +16,7 @@ class canvas { size_t getHeight(); color get(size_t x, size_t y); void set(size_t x, size_t y, color c); + void savePPM(char * path); private: size_t width; size_t height; diff --git a/src/light.cpp b/src/light.cpp index df655d5..7e742a7 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -17,6 +17,11 @@ v3 pointLight::dir(v3 p) return normalize(orig - p); } +float pointLight::d(v3 p) +{ + return mag(orig - p); +} + v3 pointLight::getColor() { return color; @@ -39,6 +44,11 @@ v3 directionalLight::dir(v3 p) return dir_; } +float directionalLight::d(v3 p) +{ + return -1; +} + v3 directionalLight::getColor() { return color; diff --git a/src/light.h b/src/light.h index 25176a3..bde9f12 100644 --- a/src/light.h +++ b/src/light.h @@ -5,6 +5,7 @@ class light { public: virtual v3 dir(v3 p) = 0; + virtual float d(v3 p) = 0; virtual v3 getColor() = 0; }; @@ -13,6 +14,7 @@ class pointLight : public light { pointLight(); pointLight(v3 orig_, v3 color_); v3 dir(v3 p) override; + float d(v3 p) override; v3 getColor() override; private: v3 orig; @@ -24,6 +26,7 @@ class directionalLight : public light { directionalLight(); directionalLight(v3 dir__, v3 color_); v3 dir(v3 p) override; + float d(v3 p) override; v3 getColor() override; private: v3 dir_; diff --git a/src/main.cpp b/src/main.cpp index c901c17..d162f65 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,6 @@ #include "render.h" #include "view.h" #include -#include #include "sphere.h" #include "plane.h" #include "light.h" @@ -34,14 +33,5 @@ int main() { render(sn, cvs, 10); - std::ofstream ofs; - ofs.open("./ppm/out.ppm", std::ios::binary); - ofs << "P6\n" << cvs->getWidth() << " " << cvs->getHeight() << "\n255\n"; - for (size_t y = 0; y < cvs->getHeight(); y++) { - for (size_t x = 0; x < cvs->getWidth(); x++) { - color c = cvs->get(x, y); - ofs << c.r << c.g << c.b; - } - } - ofs.close(); + cvs->savePPM("./ppm/out.ppm"); } \ No newline at end of file diff --git a/src/scene.cpp b/src/scene.cpp index 556358c..f865142 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -47,37 +47,30 @@ v3 scene::cast(v3 orig, v3 dir, char count, float retained) if (closestObject != nullptr) { orig = dir * closestDistance + orig; hit h = closestObject->at(orig); - - //reflection v3 hover = h.surfacen * 0.001f + orig; - v3 refld = reflect(dir, h.mappedn); - //fresnel - float albedo = std::min(h.albedo + h.albedo * fresnel(dir, refld), 1.0f); - //float albedo = h.albedo; - v3 reflColor = cast(hover, refld, count, retained * albedo); - - //lighting v3 lightColor = lighting(hover, h.mappedn); - //combine lighting and reflection - reflColor = min(reflColor * albedo + lightColor * (1 - albedo), 1); - - //transparency - /*v3 sink; - if (dir * h.surfacen < 0) { - sink = -h.surfacen * 0.001f + orig; + if (h.albedo > 0) { + v3 refld = reflect(dir, h.mappedn); + float albedo = std::min(h.albedo + h.albedo * fresnel(dir, refld), 1.0f); + v3 reflColor = cast(hover, refld, count, retained * albedo); + lightColor = min(reflColor * albedo + lightColor * (1 - albedo), 1); } - else { - sink = h.surfacen * 0.001f + orig; - } - v3 refrd = refract(dir, h.mappedn, h.refraction); - v3 refrColor = cast(sink, refrd, count, retained * (1 - h.opacity)); - //combine reflect and transparency - reflColor = min(reflColor * h.opacity + refrColor * (1 - h.opacity), 1);*/ + if (h.opacity < 1) { + v3 sink; + if (dir * h.surfacen < 0) { + sink = -h.surfacen * 0.001f + orig; + } + else { + sink = h.surfacen * 0.001f + orig; + } + v3 refrd = refract(dir, h.mappedn, h.refraction); + v3 refrColor = cast(sink, refrd, count, retained * (1 - h.opacity)); + lightColor = min(lightColor * h.opacity + refrColor * (1 - h.opacity), 1); + } - //combine all with diffuse - c = c + multiply(h.c, reflColor); + c = c + multiply(h.c, lightColor); //fog float fog = std::min(closestDistance / fogDistance, 1.0f); @@ -93,7 +86,8 @@ v3 scene::lighting(v3 orig, v3 dir) v3 c = ambient; for (light * l : lights) { v3 ldir = l->dir(orig); - if (!simpleCast(orig, ldir)) { + float ld = l->d(orig); + if (!simpleCast(orig, ldir, ld)) { float m = std::max(dir * ldir, 0.0f); c = c + l->getColor() * m; } @@ -101,10 +95,11 @@ v3 scene::lighting(v3 orig, v3 dir) return min(c, 1); } -bool scene::simpleCast(v3 orig, v3 dir) +bool scene::simpleCast(v3 orig, v3 dir, float ld) { for (object * o : objects) { - if (o->intersect(orig, dir) > 0) { + float d = o->intersect(orig, dir); + if (d > 0 && (ld < 0 || d < ld)) { return true; } } diff --git a/src/scene.h b/src/scene.h index e9427e1..4740063 100644 --- a/src/scene.h +++ b/src/scene.h @@ -13,7 +13,7 @@ class scene { view getView(); v3 cast(v3 orig, v3 dir, char count, float retained); v3 lighting(v3 orig, v3 dir); - bool simpleCast(v3 orig, v3 dir); + bool simpleCast(v3 orig, v3 dir, float ld); private: view v; std::vector objects;