【Ray Tracing in One Weekend】(ch9)Dielectrics
2017-12-25 16:04
791 查看
Chapter 9: Dielectrics
这章是关于折射的,看不太懂,这里转一篇别人的技术文章,讲的很好:http://blog.csdn.net/libing_zeng/article/details/72599121
我在这就贴贴代码和图片吧。
首先是在 Material.h 中,新添如下代码:
float Schlick(float cosine, float ref_idx) { float r0 = (1 - ref_idx) / (1 + ref_idx); r0 = r0*r0; return r0 + (1 - r0)*pow((1 - cosine), 5); } //计算折射光线的方向向量。ni_over_nt 为入射介质的折射指数和折射介质的折射指数的比值。 bool Refract(const Vec3& v, const Vec3& n, float ni_over_nt, Vec3& refracted) { Vec3 uv = unit_vector(v); float dt = dot(uv, n); float discriminant = 1.0 - ni_over_nt*ni_over_nt*(1 - dt*dt); if (discriminant > 0) { refracted = ni_over_nt*(uv - n*dt) - n*sqrt(discriminant); return true; } //根号里面的内容小于零,说明折射光线的方向向量无实根,即没有折射光线,即出现全反射。所以,折射光线函数return false else return false; } class Dielectric : public Material { public: Dielectric(float ri) : ref_idx(ri) {} virtual bool Scatter(const Ray& r_in, const hit_record& rec, Vec3& attenuation, Ray& scattered) const { Vec3 outward_normal; Vec3 reflected = Reflect(r_in.direction(), rec.normal); float ni_over_nt; attenuation = Vec3(1.0, 1.0, 1.0); Vec3 refracted; float reflect_prob; float cosine; if (dot(r_in.direction(), rec.normal) > 0) { outward_normal = -rec.normal; ni_over_nt = ref_idx; //cosine = ref_idx * dot(r_in.direction(), rec.normal) / r_in.direction().length(); cosine = dot(r_in.direction(), rec.normal) / r_in.direction().length(); cosine = sqrt(1 - ref_idx*ref_idx*(1 - cosine*cosine)); } else { outward_normal = rec.normal; ni_over_nt = 1.0 / ref_idx; cosine = -dot(r_in.direction(), rec.normal) / r_in.direction().length(); } if (Refract(r_in.direction(), outward_normal, ni_over_nt, refracted)) reflect_prob = Schlick(cosine, ref_idx); else reflect_prob = 1.0; if ((rand() % (100) / (float)(100)) < reflect_prob) scattered = Ray(rec.p, reflected); else scattered = Ray(rec.p, refracted); return true; } float ref_idx; };
Main方法中代码修改如下:
Hitable *list[5]; list[0] = new Sphere(Vec3(0.0f, 0.0f, -1.0f), 0.5f, new Lambertian(Vec3(0.8f, 0.3f, 0.3f))); list[1] = new Sphere(Vec3(0.0f, -100.5f, -1.0f), 100.0f, new Lambertian(Vec3(0.8f, 0.8f, 0.0f))); list[2] = new Sphere(Vec3(1.0f, 0.0f, -1.0f), 0.5f, new Metal(Vec3(0.8f, 0.6f, 0.2f),0.3f)); list[3] = new Sphere(Vec3(-1.0f, 0.0f, -1.0f), 0.5f, new Dielectric(1.5f)); list[4] = new Sphere(Vec3(-1.0f, 0.0f, -1.0f), -0.45f, new Dielectric(1.5f)); Hitable *world = new HitableList(list, 5);
所得如图:
相关文章推荐
- 《Ray Tracing in One Weekend》——Chapter 9: Dielectrics
- 《Ray Tracing in One Weekend》——Chapter 1: Output an image
- 《Ray Tracing in One Weekend》——Chapter 12: What's next?
- 【Ray Tracing in One Weekend】(ch7)漫反射材质
- 《Ray Tracing in One Weekend》——Chapter 2: The vec3 class
- 【Ray Tracing in One Weekend】(ch4)场景中第一个物体,球体
- 《Ray Tracing in One Weekend》——Chapter 3: Rays, a simple camera, and background
- 【Ray Tracing in One Weekend】(ch10)Positionable camera
- 《Ray Tracing in One Weekend》——Chapter 4: Adding a sphere
- 【Ray Tracing in One Weekend】(ch5)法向量的可视化与多个球的出现
- 总结《Ray Tracing in One Weekend》
- 《Ray Tracing in One Weekend》——Chapter 5: Surface normals and multiple objects
- 《Ray Tracing in One Weekend》——Chapter 6: Antialiasing
- 《Ray Tracing in One Weekend》——Chapter 7: Diffuse materials
- 《Ray Tracing in One Weekend》——Chapter 8: Metal
- 《Ray Tracing in One Weekend》——Chapter 10: Positionable camera
- 【Ray Tracing in One Weekend】(ch0~1)c++生成的第一张图片
- 【Ray Tracing in One Weekend】(ch2)世界的基石?向量
- 【Ray Tracing in One Weekend】(ch3)射线类
- 《Ray Tracing in One Weekend》——Chapter 11: Defocus Blur