-
Notifications
You must be signed in to change notification settings - Fork 335
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
26 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,9 +12,10 @@ struct Light { | |
}; | ||
|
||
struct Material { | ||
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; | ||
Material(const float &r, const Vec4f &a, const Vec3f &color, const float &spec) : refractive_index(r), albedo(a), diffuse_color(color), specular_exponent(spec) {} | ||
Material() : refractive_index(1), albedo(1,0,0,0), diffuse_color(), specular_exponent() {} | ||
float refractive_index; | ||
Vec4f albedo; | ||
Vec3f diffuse_color; | ||
float specular_exponent; | ||
}; | ||
|
@@ -44,6 +45,19 @@ Vec3f reflect(const Vec3f &I, const Vec3f &N) { | |
return I - N*2.f*(I*N); | ||
} | ||
|
||
Vec3f refract(const Vec3f &I, const Vec3f &N, const float &refractive_index) { // Snell's law | ||
float cosi = - std::max(-1.f, std::min(1.f, I*N)); | ||
float etai = 1, etat = refractive_index; | ||
Vec3f n = N; | ||
if (cosi < 0) { // if the ray is inside the object, swap the indices and invert the normal to get the correct result | ||
cosi = -cosi; | ||
std::swap(etai, etat); n = -N; | ||
} | ||
float eta = etai / etat; | ||
float k = 1 - eta*eta*(1 - cosi*cosi); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
return k < 0 ? Vec3f(0,0,0) : I*eta + n*(eta * cosi - sqrtf(k)); | ||
} | ||
|
||
bool scene_intersect(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphere> &spheres, Vec3f &hit, Vec3f &N, Material &material) { | ||
float spheres_dist = std::numeric_limits<float>::max(); | ||
for (size_t i=0; i < spheres.size(); i++) { | ||
|
@@ -67,8 +81,11 @@ Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphere> &s | |
} | ||
|
||
Vec3f reflect_dir = reflect(dir, N).normalize(); | ||
Vec3f refract_dir = refract(dir, N, material.refractive_index).normalize(); | ||
This comment has been minimized.
Sorry, something went wrong.
schoolmeister
|
||
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 refract_orig = refract_dir*N < 0 ? point - N*1e-3 : point + N*1e-3; | ||
Vec3f reflect_color = cast_ray(reflect_orig, reflect_dir, spheres, lights, depth + 1); | ||
Vec3f refract_color = cast_ray(refract_orig, refract_dir, spheres, lights, depth + 1); | ||
|
||
float diffuse_light_intensity = 0, specular_light_intensity = 0; | ||
for (size_t i=0; i<lights.size(); i++) { | ||
|
@@ -84,7 +101,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] + reflect_color*material.albedo[2]; | ||
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] + refract_color*material.albedo[3]; | ||
} | ||
|
||
void render(const std::vector<Sphere> &spheres, const std::vector<Light> &lights) { | ||
|
@@ -118,13 +135,14 @@ void render(const std::vector<Sphere> &spheres, const std::vector<Light> &lights | |
} | ||
|
||
int main() { | ||
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.); | ||
Material ivory(1.0, Vec4f(0.6, 0.3, 0.1, 0.0), Vec3f(0.4, 0.4, 0.3), 50.); | ||
Material glass(1.5, Vec4f(0.0, 0.5, 0.1, 0.8), Vec3f(0.6, 0.7, 0.8), 125.); | ||
Material red_rubber(1.0, Vec4f(0.9, 0.1, 0.0, 0.0), Vec3f(0.3, 0.1, 0.1), 10.); | ||
Material mirror(1.0, Vec4f(0.0, 10.0, 0.8, 0.0), 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, mirror)); | ||
spheres.push_back(Sphere(Vec3f(-1.0, -1.5, -12), 2, glass)); | ||
spheres.push_back(Sphere(Vec3f( 1.5, -0.5, -18), 3, red_rubber)); | ||
spheres.push_back(Sphere(Vec3f( 7, 5, -18), 4, mirror)); | ||
|
||
|
Check the "vector form" section from the Snell's law wiki article:
https://en.wikipedia.org/wiki/Snell%27s_law
in particular, this formula: