From dfcd78f3f458d8c4bfbc27b08ced5aae0f2e57d4 Mon Sep 17 00:00:00 2001 From: Roland Hieber Date: Mon, 25 Jan 2010 15:43:29 +0100 Subject: [PATCH 1/1] code for assignment 3 --- EyeLightShader.cxx | 9 +- EyeLightShader.hxx | 7 +- FlatShader.cxx | 4 +- Image.cxx | 26 ++--- InfinitePlane.cxx | 10 +- Makefile | 6 +- MicroTrace.cxx | 202 ++++++++++++++--------------------- Primitive.cxx | 2 +- Primitive.hxx | 2 +- Ray.cxx | 42 +++++--- Ray.hxx | 11 +- ReflectiveEyeLightShader.cxx | 42 +++++--- Scene.cxx | 45 ++++---- Scene.hxx | 7 +- Shader.hxx | 2 + Sphere.cxx | 32 +++--- Triangle.cxx | 30 +++--- Triangle.hxx | 1 + Vec3f.cxx | 12 +++ Vec3f.hxx | 4 +- 20 files changed, 246 insertions(+), 250 deletions(-) diff --git a/EyeLightShader.cxx b/EyeLightShader.cxx index 8eae610..4f31b84 100644 --- a/EyeLightShader.cxx +++ b/EyeLightShader.cxx @@ -21,9 +21,8 @@ EyeLightShader::EyeLightShader() Vec3f EyeLightShader::Shade(Ray& ray) { - // shade according to cos(theta) - Vec3f r = ray.direction(); - Vec3f n = ray.hit()->GetNormal(ray); - float cos_theta = fabs(r.dot(n) / (r.norm() * n.norm())); - return m_color * cos_theta; + Vec3f N = ray.hit()->GetNormal(ray); + float cos_phi = fabs(ray.direction().dot(N)); + + return m_color * cos_phi; } diff --git a/EyeLightShader.hxx b/EyeLightShader.hxx index 9b4777e..2d0bfe5 100644 --- a/EyeLightShader.hxx +++ b/EyeLightShader.hxx @@ -10,11 +10,10 @@ public: virtual ~EyeLightShader(); virtual Vec3f Shade(Ray& ray); - -protected: - Vec3f m_color; - private: EyeLightShader(); + +protected: + Vec3f m_color; }; #endif diff --git a/FlatShader.cxx b/FlatShader.cxx index 3699cd4..210fc6f 100644 --- a/FlatShader.cxx +++ b/FlatShader.cxx @@ -12,7 +12,7 @@ FlatShader::~FlatShader() } FlatShader::FlatShader() - : Shader(0), + : Shader(0), m_color(Vec3f()) { } @@ -20,5 +20,5 @@ FlatShader::FlatShader() Vec3f FlatShader::Shade(Ray& ray) { - return m_color; + return m_color; } diff --git a/Image.cxx b/Image.cxx index 899ac6f..b45cac9 100644 --- a/Image.cxx +++ b/Image.cxx @@ -39,39 +39,31 @@ Image::operator()(int x, int y) { assert(x >= 0 && x < m_resX); assert(y >= 0 && y < m_resY); - - return m_pixel[y*m_resX+x]; + + return m_pixel[y*m_resX+x]; } void Image::WritePPM(const std::string& fileName) { std::cerr << "(Image): Writing to file " << fileName << std::endl; std::ofstream file(fileName.c_str()); - + if(!file.is_open()) { std::cerr << "(Image): Could not open file " << fileName << std::endl; return; } - + file << "P3" << std::endl; file << m_resX << " " << m_resY << " " << 255 << std::endl; - for (int y=m_resY-1;y>=0;y--) + for (int y=m_resY-1;y>=0;y--) { for (int x=0;x 255) cur[0] = 255; - if(cur[1] > 255) cur[1] = 255; - if(cur[2] > 255) cur[2] = 255; - - file - << (int)(255.99999999 * cur[0]) << " " - << (int)(255.99999999 * cur[1]) << " " - << (int)(255.99999999 * cur[2]) << " " + file + << (int)(255.99999999 * (*this)(x,y)[0]) << " " + << (int)(255.99999999 * (*this)(x,y)[1]) << " " + << (int)(255.99999999 * (*this)(x,y)[2]) << " " << "\t"; } file << std::endl; diff --git a/InfinitePlane.cxx b/InfinitePlane.cxx index 54c9570..f73d835 100644 --- a/InfinitePlane.cxx +++ b/InfinitePlane.cxx @@ -1,11 +1,11 @@ #include "InfinitePlane.hxx" InfinitePlane::InfinitePlane(const Vec3f& a, const Vec3f& n, Shader* shader) - : Primitive(shader), + : Primitive(shader), m_a(a), m_n(n) { - + } InfinitePlane::~InfinitePlane() @@ -17,15 +17,17 @@ InfinitePlane::Intersect(Ray& ray) { Vec3f diff = m_a - ray.origin(); float t = diff.dot(m_n) / ray.direction().dot(m_n); - if (t < 1e-5 || t > ray.t()) + if (t < Epsilon || t > ray.t()) return false; + ray.setT(t); + ray.setHit(this); + return true; } Vec3f InfinitePlane::GetNormal(Ray& ray) { - // We already have the surface normal return m_n; } diff --git a/Makefile b/Makefile index a9276b7..f263909 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ all: MicroTrace CC = g++ -CFLAGS = -O0 -g -Wall +CFLAGS = -O3 -Wall OBJ = MicroTrace.o\ @@ -19,6 +19,10 @@ OBJ = MicroTrace.o\ FlatShader.o\ EyeLightShader.o\ ReflectiveEyeLightShader.o\ + PhongShader.o\ + Light.o\ + PointLight.o\ + SpotLight.o\ Scene.o\ Primitive.o diff --git a/MicroTrace.cxx b/MicroTrace.cxx index 4689425..e0fd688 100644 --- a/MicroTrace.cxx +++ b/MicroTrace.cxx @@ -10,21 +10,24 @@ #include "FlatShader.hxx" #include "EyeLightShader.hxx" #include "ReflectiveEyeLightShader.hxx" +#include "PhongShader.hxx" +#include "PointLight.hxx" +#include "SpotLight.hxx" #include "Scene.hxx" -void RenderFrameFlat(const std::string& fileName) + +void RenderFramePhongPointLight(const std::string& fileName) { /* Scene definition */ - Scene scene; - + /* Flat shaders */ - FlatShader shd1(&scene, Vec3f(1,0,0)); // red surface - FlatShader shd2(&scene, Vec3f(0,1,0)); // green surface - FlatShader shd3(&scene, Vec3f(0,0,1)); // blue surface - FlatShader shd4(&scene, Vec3f(1,1,0)); // yellow surface - FlatShader shd5(&scene, Vec3f(0,1,1)); // cyan surface - FlatShader shd6(&scene, Vec3f(1,1,1)); // white surface + PhongShader shd1(&scene, Vec3f(1,0,0),Vec3f(1,0,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // red surface + PhongShader shd2(&scene, Vec3f(0,1,0),Vec3f(0,1,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // green surface + PhongShader shd3(&scene, Vec3f(0,0,1),Vec3f(0,0,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // blue surface + PhongShader shd4(&scene, Vec3f(1,1,0),Vec3f(1,1,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // yellow surface + PhongShader shd5(&scene, Vec3f(0,1,1),Vec3f(0,1,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // cyan surface + PhongShader shd6(&scene, Vec3f(1,1,1),Vec3f(1,1,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // white surface /* scene objects */ Sphere s1(Vec3f(-2,1.7,0), 2, &shd1); @@ -32,57 +35,61 @@ void RenderFrameFlat(const std::string& fileName) Sphere s3(Vec3f(3,0.8,-2), 2, &shd3); InfinitePlane p1(Vec3f(0,-1,0),Vec3f(0,1,0), &shd4); - - Triangle t1(Vec3f(-2,3,1),Vec3f(1,2,1),Vec3f(3,2.8,3), &shd5); - + + Triangle t1(Vec3f(-2,3,1),Vec3f(1,2,1),Vec3f(3,2.8,3), &shd5); + /* add to scene */ scene.Add(&s1); scene.Add(&s2); scene.Add(&s3); scene.Add(&p1); scene.Add(&t1); + + /* light sources */ + Vec3f lightPosition1(4,5,6); + Vec3f lightPosition2(-3,5,4); + Vec3f pointLightSourceIntensity(50,50,50); + + PointLight pointLight1(&scene, lightPosition1, pointLightSourceIntensity); + PointLight pointLight2(&scene, lightPosition2, pointLightSourceIntensity); + + scene.Add(&pointLight1); + scene.Add(&pointLight2); Image img(scene.camera()->resX(),scene.camera()->resY()); // image array Ray ray; // primary ray - + for(int y = 0; y < scene.camera()->resY(); y++) { - for (int x = 0; x < scene.camera()->resX(); x++) - { - - /* Initialize your ray here */ - // shoot four rays for antialiasing - scene.camera()->InitRay(x+0.5,y+0.5, ray); // initialize ray - Vec3f col1 = scene.RayTrace(ray); - scene.camera()->InitRay(x-0.5,y+0.5, ray); // initialize ray - Vec3f col2 = scene.RayTrace(ray); - scene.camera()->InitRay(x-0.5,y-0.5, ray); // initialize ray - Vec3f col3 = scene.RayTrace(ray); - scene.camera()->InitRay(x-0.5,y-0.5, ray); // initialize ray - Vec3f col4 = scene.RayTrace(ray); - - img(x,y) = (col1 + col2 + col3 + col4) / 4.0; // store pixel color - //std::cerr << "Main: Image color = " << img(x,y) << std::endl; - } + for (int x = 0; x < scene.camera()->resX(); x++) + { + + /* Initialize your ray here */ + + scene.camera()->InitRay(x+0.5,y+0.5,ray); // initialize ray + + Vec3f col = scene.RayTrace(ray); + + img(x,y) = col; // store pixel color + //std::cerr << "Main: Image color = " << img(x,y) << std::endl; + } } img.WritePPM(fileName); // write final image } - -void RenderFrameEyeLight(const std::string& fileName) +void RenderFramePhongSpotLight(const std::string& fileName) { /* Scene definition */ - Scene scene; - + /* Flat shaders */ - EyeLightShader shd1(&scene, Vec3f(1,0,0)); // red surface - EyeLightShader shd2(&scene, Vec3f(0,1,0)); // green surface - EyeLightShader shd3(&scene, Vec3f(0,0,1)); // blue surface - EyeLightShader shd4(&scene, Vec3f(1,1,0)); // yellow surface - EyeLightShader shd5(&scene, Vec3f(0,1,1)); // cyan surface - EyeLightShader shd6(&scene, Vec3f(1,1,1)); // white surface + PhongShader shd1(&scene, Vec3f(1,0,0),Vec3f(1,0,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // red surface + PhongShader shd2(&scene, Vec3f(0,1,0),Vec3f(0,1,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // green surface + PhongShader shd3(&scene, Vec3f(0,0,1),Vec3f(0,0,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // blue surface + PhongShader shd4(&scene, Vec3f(1,1,0),Vec3f(1,1,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // yellow surface + PhongShader shd5(&scene, Vec3f(0,1,1),Vec3f(0,1,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // cyan surface + PhongShader shd6(&scene, Vec3f(1,1,1),Vec3f(1,1,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // white surface /* scene objects */ Sphere s1(Vec3f(-2,1.7,0), 2, &shd1); @@ -90,105 +97,60 @@ void RenderFrameEyeLight(const std::string& fileName) Sphere s3(Vec3f(3,0.8,-2), 2, &shd3); InfinitePlane p1(Vec3f(0,-1,0),Vec3f(0,1,0), &shd4); - - Triangle t1(Vec3f(-2,3,1),Vec3f(1,2,1),Vec3f(3,2.8,3), &shd5); - - /* add to scene */ - scene.Add(&s1); - scene.Add(&s2); - scene.Add(&s3); - scene.Add(&p1); - scene.Add(&t1); - - Image img(scene.camera()->resX(),scene.camera()->resY()); // image array - Ray ray; // primary ray - - for(int y = 0; y < scene.camera()->resY(); y++) - { - for (int x = 0; x < scene.camera()->resX(); x++) - { - - /* Initialize your ray here */ - // shoot four rays for antialiasing - scene.camera()->InitRay(x+0.5,y+0.5, ray); // initialize ray - Vec3f col1 = scene.RayTrace(ray); - scene.camera()->InitRay(x-0.5,y+0.5, ray); // initialize ray - Vec3f col2 = scene.RayTrace(ray); - scene.camera()->InitRay(x-0.5,y-0.5, ray); // initialize ray - Vec3f col3 = scene.RayTrace(ray); - scene.camera()->InitRay(x-0.5,y-0.5, ray); // initialize ray - Vec3f col4 = scene.RayTrace(ray); - - img(x,y) = (col1 + col2 + col3 + col4) / 4.0; // store pixel color - } - } - img.WritePPM(fileName); // write final image -} - -void RenderFrameReflectiveEyeLight(const std::string& fileName) -{ - /* Scene definition */ - - Scene scene; - - /* Flat shaders */ - ReflectiveEyeLightShader shd1(&scene, 1.0, Vec3f(1,0,0)); // red surface - ReflectiveEyeLightShader shd2(&scene, 1.0, Vec3f(0.0,1.0,0.0)); // green surface - ReflectiveEyeLightShader shd3(&scene, 1.0, Vec3f(0,0,1)); // blue surface - ReflectiveEyeLightShader shd4(&scene, 0.8, Vec3f(1,1,0)); // yellow surface - ReflectiveEyeLightShader shd5(&scene, 1.0, Vec3f(0,1,1)); // cyan surface - ReflectiveEyeLightShader shd6(&scene, 0.0, Vec3f(1,1,1)); // white surface - - /* scene objects */ - Sphere s1(Vec3f(-2,1.7,0), 2, &shd1); - Sphere s2(Vec3f(0.4,-1,1), 2.0, &shd2); - Sphere s3(Vec3f(3,0.8,-2), 2, &shd3); - InfinitePlane p1(Vec3f(0,-1,0),Vec3f(0,1,0), &shd4); - - - Triangle t1(Vec3f(-2,3,1),Vec3f(1,2,1),Vec3f(3,2.8,3), &shd5); - + + Triangle t1(Vec3f(-2,3,1),Vec3f(1,2,1),Vec3f(3,2.8,3), &shd5); + /* add to scene */ scene.Add(&s1); scene.Add(&s2); scene.Add(&s3); scene.Add(&p1); scene.Add(&t1); + + /* light sources */ + Vec3f lightPosition1(4,5,6); + Vec3f lightPosition2(-3,5,4); + Vec3f spotLightSourceIntensity(50,50,50); + Vec3f lightDir1 = lightPosition1 * (-1.0f); + lightDir1.normalize(); + Vec3f lightDir2 = lightPosition2 *(-1.0f); + lightDir2.normalize(); + float alpha_min = 15.0f; + float alpha_max = 30.0f; + + SpotLight spotLight1(&scene, lightPosition1, lightDir1, spotLightSourceIntensity, alpha_min, alpha_max); + SpotLight spotLight2(&scene, lightPosition2, lightDir2, spotLightSourceIntensity, alpha_min, alpha_max); + + scene.Add(&spotLight1); + scene.Add(&spotLight2); Image img(scene.camera()->resX(),scene.camera()->resY()); // image array Ray ray; // primary ray - + for(int y = 0; y < scene.camera()->resY(); y++) { - for (int x = 0; x < scene.camera()->resX(); x++) - { - /* Initialize your ray here */ //int x = 319, y = 59; - // shoot four rays for antialiasing - scene.camera()->InitRay(x+0.5,y+0.5, ray); // initialize ray - Vec3f col1 = scene.RayTrace(ray); - scene.camera()->InitRay(x-0.5,y+0.5, ray); // initialize ray - Vec3f col2 = scene.RayTrace(ray); - scene.camera()->InitRay(x-0.5,y-0.5, ray); // initialize ray - Vec3f col3 = scene.RayTrace(ray); - scene.camera()->InitRay(x-0.5,y-0.5, ray); // initialize ray - Vec3f col4 = scene.RayTrace(ray); - - img(x,y) = (col1 + col2 + col3 + col4) / 4.0; // store pixel color - //std::cerr << "Main: Image color = " << img(x,y) << std::endl; - } + for (int x = 0; x < scene.camera()->resX(); x++) + { + + /* Initialize your ray here */ + + scene.camera()->InitRay(x+0.5,y+0.5,ray); // initialize ray + + Vec3f col = scene.RayTrace(ray); + + img(x,y) = col; // store pixel color + //std::cerr << "Main: Image color = " << img(x,y) << std::endl; + } } img.WritePPM(fileName); // write final image } - - #define RESX 640 // image x-resolution #define RESY 480 // image y-resolution int main(int, char**) { - //RenderFrameFlat("flatshaded.ppm"); - //RenderFrameEyeLight("eyelight.ppm"); - RenderFrameReflectiveEyeLight("reflective.ppm"); + RenderFramePhongPointLight("phong_point.ppm"); + RenderFramePhongSpotLight("phong_spot.ppm"); } diff --git a/Primitive.cxx b/Primitive.cxx index 850cb24..4c8cf94 100644 --- a/Primitive.cxx +++ b/Primitive.cxx @@ -16,7 +16,7 @@ Primitive::Occluded(Ray& ray) } Shader* -Primitive::shader() +Primitive::shader() { return m_shader; } diff --git a/Primitive.hxx b/Primitive.hxx index 04e201f..68dd11c 100644 --- a/Primitive.hxx +++ b/Primitive.hxx @@ -13,8 +13,8 @@ public: virtual bool Intersect(Ray &ray) = 0; virtual bool Occluded(Ray& ray); virtual Vec3f GetNormal(Ray& ray) = 0; - Shader* shader(); + protected: Shader* m_shader; }; diff --git a/Ray.cxx b/Ray.cxx index e0a1ab5..84617d1 100644 --- a/Ray.cxx +++ b/Ray.cxx @@ -2,22 +2,23 @@ #include "Ray.hxx" -#define MAX_RECURSION_DEPTH 10 - Ray::Ray() : m_org(Vec3f()), m_dir(Vec3f()), - m_level(MAX_RECURSION_DEPTH), + m_level(0), + m_density(1.0), m_hit(0) { m_t = std::numeric_limits::max(); } -Ray::Ray(const Vec3f& org, - const Vec3f& dir) +Ray::Ray(const Vec3f& org, + const Vec3f& dir, + unsigned int recursion_level) : m_org(org), m_dir(dir), - m_level(MAX_RECURSION_DEPTH), + m_level(recursion_level), + m_density(1.0), m_hit(0) { m_t = std::numeric_limits::max(); @@ -34,6 +35,7 @@ Ray::Ray(const Ray& r) m_t = r.m_t; m_hit = r.m_hit; m_level = r.m_level; + m_density = r.m_density; } Ray& @@ -45,6 +47,8 @@ Ray::operator=(const Ray& r) m_dir = r.m_dir; m_t = r.m_t; m_hit = r.m_hit; + m_level = r.m_level; + m_density = r.m_density; } return *this; } @@ -85,19 +89,19 @@ Ray::setT(float t) m_t = t; } -void -Ray::setHit(Primitive * p) -{ - m_hit = p; -} - Primitive* Ray::hit() { return m_hit; } -unsigned int +void +Ray::setHit(Primitive* p) +{ + m_hit = p; +} + +unsigned int Ray::recursionDepth() const { return m_level; @@ -108,3 +112,15 @@ Ray::setRecursionDepth(unsigned int i) { m_level = i; } + +float +Ray::indexOfRefraction() const +{ + return m_density; +} + +void +Ray::setIndexOfRefraction(float d) +{ + m_density = d; +} diff --git a/Ray.hxx b/Ray.hxx index 0b4e796..0ec9f76 100644 --- a/Ray.hxx +++ b/Ray.hxx @@ -9,29 +9,32 @@ class Ray { public: Ray(); - Ray(const Vec3f& org, const Vec3f& dir); + Ray(const Vec3f& org, const Vec3f& dir, unsigned int recursion_level = 0); ~Ray(); Ray(const Ray& r); Ray& operator=(const Ray& r); - + const Vec3f& origin() const; const Vec3f& direction() const; float t() const; - void setHit(Primitive * p); Primitive* hit(); unsigned int recursionDepth() const; + float indexOfRefraction() const; void setOrigin(const Vec3f& o); void setDir(const Vec3f& d); void setT(float t); + void setHit(Primitive* p); void setRecursionDepth(unsigned int i); + void setIndexOfRefraction(float ior); private: Vec3f m_org; //!< ray origin Vec3f m_dir; //!< ray direction float m_t; //!< current/maximum hit distance - + unsigned int m_level; //!< level of recursion + float m_density; //!< index of refraction Primitive* m_hit; }; diff --git a/ReflectiveEyeLightShader.cxx b/ReflectiveEyeLightShader.cxx index b681e47..0adb174 100644 --- a/ReflectiveEyeLightShader.cxx +++ b/ReflectiveEyeLightShader.cxx @@ -23,20 +23,30 @@ ReflectiveEyeLightShader::ReflectiveEyeLightShader() Vec3f ReflectiveEyeLightShader::Shade(Ray& ray) { - Vec3f eyeColor = EyeLightShader::Shade(ray); - Vec3f reflColor; - - if(ray.recursionDepth() > 0) { - m_scene->Intersect(ray); - // intersection, - Epsilon to avoid numerical problems and getting the - // reflection on the object's inside ;-) - Vec3f i = ray.origin() + ray.direction() * (ray.t() - Epsilon); - Vec3f r = ray.direction(); - Vec3f n = (ray.hit()->GetNormal(ray)); - - Ray sec(i, r + n * (2 * r.dot(n * -1))); - sec.setRecursionDepth(ray.recursionDepth() - 1); - reflColor = m_scene->RayTrace(sec); - } - return eyeColor + reflColor * m_reflectivity; + Vec3f N = ray.hit()->GetNormal(ray); + + // diffuse color + Vec3f color = EyeLightShader::Shade(ray); + + // add reflection + if(ray.recursionDepth() < RecursionDepth) + { + // generate reflected ray + // ray origin = hitpoint + Vec3f origin = ray.origin() + ray.direction()*ray.t(); + Vec3f dir = ray.direction()-N*2*N.dot(ray.direction()); + dir.normalize(); + + // spawn new ray + Ray reflection_ray(origin, dir, ray.recursionDepth()+1); + reflection_ray.setT(Infinity); + + // trace reflection ray + Vec3f reflected_color = m_scene->RayTrace(reflection_ray); + color += reflected_color * m_reflectivity; + } + + color.clamp(); + + return color; } diff --git a/Scene.cxx b/Scene.cxx index 4998bd1..bbd6785 100644 --- a/Scene.cxx +++ b/Scene.cxx @@ -1,13 +1,12 @@ #include "Scene.hxx" #include "PerspectiveCamera.hxx" -#include Scene::Scene() - : m_camera(new PerspectiveCamera(Vec3f(0,0,8), - Vec3f(0,0,-1), - Vec3f(0,1,0), - 50, - 640, + : m_camera(new PerspectiveCamera(Vec3f(0,0,8), + Vec3f(0,0,-1), + Vec3f(0,1,0), + 50, + 640, 480) ), m_bgColor(Vec3f(0,0,0)) @@ -30,29 +29,28 @@ Scene::operator=(const Scene& s) return *this; } -void +void Scene::Add(Primitive* p) { m_primitives.push_back(p); } +void +Scene::Add(Light* l) +{ +} bool Scene::Intersect(Ray& ray) { - bool hit = false; - float t = std::numeric_limits::max(); - for (std::vector::iterator i = m_primitives.begin(); - i != m_primitives.end(); i++) { - // store closest object hit - if (hit |= (*i)->Intersect(ray)) { - if (ray.t() < t) { - ray.setHit(*i); - t = ray.t(); - } + bool intersect = false; + + for(unsigned int i = 0; i < m_primitives.size(); ++i) + { + intersect |= m_primitives[i]->Intersect(ray); } - } - return hit; + + return intersect; } bool @@ -64,14 +62,11 @@ Scene::Occluded(Ray& ray) Vec3f Scene::RayTrace(Ray& ray) { - if (Intersect(ray)) { - return ray.hit()->shader()->Shade(ray); - } else { - return Vec3f(0,0,0); - } + bool intersect = this->Intersect(ray); + return (intersect) ? ray.hit()->shader()->Shade(ray) : m_bgColor; } -const Camera* +const Camera* Scene::camera() const { return m_camera; diff --git a/Scene.hxx b/Scene.hxx index 18deb79..b92e9e5 100644 --- a/Scene.hxx +++ b/Scene.hxx @@ -5,6 +5,7 @@ #include "Ray.hxx" #include "Camera.hxx" +#include "Light.hxx" #include "Primitive.hxx" class Scene @@ -15,7 +16,9 @@ public: // add another primitive to the scene void Add(Primitive* p); - + // add another light source to the scene + void Add(Light* l); + // intersect the ray with all objects in the scene virtual bool Intersect(Ray& ray); // find occluder @@ -35,5 +38,7 @@ private: // primitives std::vector m_primitives; + // lights + std::vector m_lights; }; #endif diff --git a/Shader.hxx b/Shader.hxx index ac6de1d..98e591f 100644 --- a/Shader.hxx +++ b/Shader.hxx @@ -7,6 +7,8 @@ // forward declaration class Scene; +#define RecursionDepth 10 + class Shader { public: diff --git a/Sphere.cxx b/Sphere.cxx index 77d4320..6b8d943 100644 --- a/Sphere.cxx +++ b/Sphere.cxx @@ -1,7 +1,7 @@ #include "Sphere.hxx" Sphere::Sphere(const Vec3f& center, float radius, Shader* shader) - : Primitive(shader), + : Primitive(shader), m_center(center), m_radius(radius) { @@ -20,39 +20,31 @@ Sphere::Intersect(Ray& ray) if( B*B-4*A*C < 0 ) return false; - + float root = sqrtf(B*B-4*A*C); float t = (-B-root)/(2.0f*A); if(t > ray.t()) return false; - - if( t < 1e-6 ) + + if( t < Epsilon ) { t = (-B+root)/(2.0f*A); - if( t < 1e-6 || t > ray.t()) + if( t < Epsilon || t > ray.t()) return false; } + ray.setT(t); + ray.setHit(this); + return true; } Vec3f Sphere::GetNormal(Ray& ray) { - // We don't want to modify the ray (probably this is not needed, but I am - // too lazy to think about it now ...) - Ray tempRay = ray; + Vec3f p = ray.origin()+ray.direction()*ray.t(); + Vec3f N = (p-m_center); + N.normalize(); - // Surface normal is the difference between intersection and center point - if(Intersect(tempRay)) { - // intersection point - Vec3f i = tempRay.origin() + tempRay.direction() * (tempRay.t() - Epsilon); - // normal - Vec3f n = (i - m_center); - n.normalize(); - return n; - } else { - // no intersection with ray, so no surface normal - return Vec3f(0,0,0); - } + return N; } diff --git a/Triangle.cxx b/Triangle.cxx index 456c6d8..498757e 100644 --- a/Triangle.cxx +++ b/Triangle.cxx @@ -7,8 +7,10 @@ Triangle::Triangle(const Vec3f& a, : Primitive(shader), m_a(a), m_b(b), - m_c(c) + m_c(c), + m_n( (b-a).cross(c-a) ) { + m_n.normalize(); } Triangle::~Triangle() @@ -20,34 +22,35 @@ Triangle::Intersect(Ray& ray) { const Vec3f edge1 = m_b-m_a; const Vec3f edge2 = m_c-m_a; - + const Vec3f pvec = ray.direction().cross(edge2); - + const float det = edge1.dot(pvec); if (fabs(det) < Epsilon) return false; - + const float inv_det = 1.0f / det; - + const Vec3f tvec = ray.origin()-m_a; float lambda = tvec.dot( pvec ); lambda *= inv_det; - - if (lambda < 0.0f || lambda > 1.0f) + + if (lambda < 0.0f || lambda > 1.0f) return false; const Vec3f qvec = tvec.cross(edge1); float mue = ray.direction().dot(qvec); mue *= inv_det; - - if (mue < 0.0f || mue+lambda > 1.0f) + + if (mue < 0.0f || mue+lambda > 1.0f) return false; float f = edge2.dot(qvec); f *= inv_det; - if (ray.t() <= f || f < 1e-4 ) + if (ray.t() <= f || f < Epsilon ) return false; - + ray.setT(f); + ray.setHit(this); return true; } @@ -55,8 +58,5 @@ Triangle::Intersect(Ray& ray) Vec3f Triangle::GetNormal(Ray& ray) { - // normal is cross product of spanning vectors - Vec3f n = (m_c - m_a) % (m_c - m_b); - n.normalize(); - return n; + return m_n; } diff --git a/Triangle.hxx b/Triangle.hxx index fbf4e2c..6abbe53 100644 --- a/Triangle.hxx +++ b/Triangle.hxx @@ -13,5 +13,6 @@ public: virtual Vec3f GetNormal(Ray& ray); private: Vec3f m_a, m_b, m_c; + Vec3f m_n; }; #endif diff --git a/Vec3f.cxx b/Vec3f.cxx index f656d29..7c39435 100644 --- a/Vec3f.cxx +++ b/Vec3f.cxx @@ -211,3 +211,15 @@ Vec3f::operator[](unsigned int i) assert(i < 3); return m_values[i]; } + +void +Vec3f::clamp() +{ + for(unsigned int i = 0; i < 3; ++i) + { + if(m_values[i] < 0.0) + m_values[i] = 0.0; + if(m_values[i] > 1.0) + m_values[i] = 1.0; + } +} diff --git a/Vec3f.hxx b/Vec3f.hxx index 6b67d5b..81c0c8b 100644 --- a/Vec3f.hxx +++ b/Vec3f.hxx @@ -11,7 +11,7 @@ #endif -#define Epsilon 1E-4 +#define Epsilon 1E-3 #define Infinity HUGE_VAL //! Standard operators and useful methods for 3d vectors @@ -68,6 +68,8 @@ public: float operator[](unsigned int i) const; float& operator[](unsigned int i); + //! clamp each element to [0,1] + void clamp(); private: float m_values[3]; }; -- 2.20.1