Skip to content
Permalink
Browse files

reflections

  • Loading branch information
ssloy committed Jan 20, 2019
1 parent ef70d13 commit c80479d1d22fe98f41b584972affeb43422a23a6
Showing with 15 additions and 10 deletions.
  1. BIN out.jpg
  2. +15 −10 tinyraytracer.cpp
BIN -9.37 KB (81%) out.jpg
Binary file not shown.
@@ -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;
};
@@ -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();
@@ -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) {
@@ -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));

0 comments on commit c80479d

Please sign in to comment.
You can’t perform that action at this time.