Skip to content

Commit

Permalink
reflections
Browse files Browse the repository at this point in the history
  • Loading branch information
ssloy committed Jan 20, 2019
1 parent ef70d13 commit c80479d
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 10 deletions.
Binary file modified out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 15 additions & 10 deletions tinyraytracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ struct Light {
};

struct Material {
Material(const Vec2f &a, const Vec3f &color, const float &spec) : albedo(a), diffuse_color(color), specular_exponent(spec) {}
Material() : albedo(1,0), diffuse_color(), specular_exponent() {}
Vec2f albedo;
Material(const Vec3f &a, const Vec3f &color, const float &spec) : albedo(a), diffuse_color(color), specular_exponent(spec) {}
Material() : albedo(1,0,0), diffuse_color(), specular_exponent() {}
Vec3f albedo;
Vec3f diffuse_color;
float specular_exponent;
};
Expand Down Expand Up @@ -58,14 +58,18 @@ bool scene_intersect(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphe
return spheres_dist<1000;
}

Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphere> &spheres, const std::vector<Light> &lights) {
Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphere> &spheres, const std::vector<Light> &lights, size_t depth=0) {
Vec3f point, N;
Material material;

if (!scene_intersect(orig, dir, spheres, point, N, material)) {
if (depth>4 || !scene_intersect(orig, dir, spheres, point, N, material)) {
return Vec3f(0.2, 0.7, 0.8); // background color
}

Vec3f reflect_dir = reflect(dir, N).normalize();

This comment has been minimized.

Copy link
@cl0ne

cl0ne Jan 27, 2019

I suppose we don't need normalize here because dir and N are already unit vectors and reflection doesn't change vector norm or I'm wrong?

This comment has been minimized.

Copy link
@ssloy

ssloy Jan 27, 2019

Author Owner

Reflection direction is computed as I - N*2.f*(I*N), where N is the surface normal and I is the incident angle. This formula is valid only if N and I are normalized, however I am not sure that it necessarily produces a normalized vector. Let us check. ( I - N*2*(I*N) )^2 = I^2 + [N*2*(I*N)]^2 - 2*I*N*2*(I*N) = I^2 + [2*(I*N)]^2 * (N^2- 1) = 1. Yup, you are right, this normalize() is not necessary. However it is not extremely expensive and it reassures me :)

Vec3f reflect_orig = reflect_dir*N < 0 ? point - N*1e-3 : point + N*1e-3; // offset the original point to avoid occlusion by the object itself
Vec3f reflect_color = cast_ray(reflect_orig, reflect_dir, spheres, lights, depth + 1);

float diffuse_light_intensity = 0, specular_light_intensity = 0;
for (size_t i=0; i<lights.size(); i++) {
Vec3f light_dir = (lights[i].position - point).normalize();
Expand All @@ -80,7 +84,7 @@ Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphere> &s
diffuse_light_intensity += lights[i].intensity * std::max(0.f, light_dir*N);
specular_light_intensity += powf(std::max(0.f, -reflect(-light_dir, N)*dir), material.specular_exponent)*lights[i].intensity;
}
return material.diffuse_color * diffuse_light_intensity * material.albedo[0] + Vec3f(1., 1., 1.)*specular_light_intensity * material.albedo[1];
return material.diffuse_color * diffuse_light_intensity * material.albedo[0] + Vec3f(1., 1., 1.)*specular_light_intensity * material.albedo[1] + reflect_color*material.albedo[2];
}

void render(const std::vector<Sphere> &spheres, const std::vector<Light> &lights) {
Expand Down Expand Up @@ -114,14 +118,15 @@ void render(const std::vector<Sphere> &spheres, const std::vector<Light> &lights
}

int main() {
Material ivory(Vec2f(0.6, 0.3), Vec3f(0.4, 0.4, 0.3), 50.);
Material red_rubber(Vec2f(0.9, 0.1), Vec3f(0.3, 0.1, 0.1), 10.);
Material ivory(Vec3f(0.6, 0.3, 0.1), Vec3f(0.4, 0.4, 0.3), 50.);
Material red_rubber(Vec3f(0.9, 0.1, 0.0), Vec3f(0.3, 0.1, 0.1), 10.);
Material mirror(Vec3f(0.0, 10.0, 0.8), Vec3f(1.0, 1.0, 1.0), 1425.);

std::vector<Sphere> spheres;
spheres.push_back(Sphere(Vec3f(-3, 0, -16), 2, ivory));
spheres.push_back(Sphere(Vec3f(-1.0, -1.5, -12), 2, red_rubber));
spheres.push_back(Sphere(Vec3f(-1.0, -1.5, -12), 2, mirror));
spheres.push_back(Sphere(Vec3f( 1.5, -0.5, -18), 3, red_rubber));
spheres.push_back(Sphere(Vec3f( 7, 5, -18), 4, ivory));
spheres.push_back(Sphere(Vec3f( 7, 5, -18), 4, mirror));

std::vector<Light> lights;
lights.push_back(Light(Vec3f(-20, 20, 20), 1.5));
Expand Down

0 comments on commit c80479d

Please sign in to comment.