您的位置:首页 > 其它

【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);


所得如图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: