您的位置:首页 > 其它

【Ray Tracing in One Weekend】(ch7)漫反射材质

2017-12-12 15:44 931 查看

Chapter 7: Diffuse Materials

首先回忆一下,第一次我们给球体赋予颜色时,是直接规定,撞到球体的那点颜色为红色,所以整个球为红色。

第二次,我们把撞点颜色改为法向量映射的颜色。

这一次,我们假设球体是漫反射模型,我们让射线撞到球体后,继续反射,遇到物体就反射,直到撞到“背景”为止,然后把背景颜色逐级返回(返回途中颜色会被一直吸收,变化),直至Camera,这样,我们最后获得的该像素块的颜色就是k*背景色。

关于漫反射材质,我们有以下几点需要知道:

不发光的漫反射物体仅仅呈现其周围的颜色,但是它们会用自己的固有颜色进行调制。

从漫反射面反射的光的方向是随机的。

光线不仅被反射,还会被吸收,所以有些物体会看起来很暗。

那么,射线撞在球体上后,往哪个方向反射呢?这里我们用一种数学方法解决:

用撞点p以及其表面法向N确定单位球体,然后从球体上随机取一点s,由p指向s的射线(红色)即为我们反射出去的下一条射线。



用代码求得球体上随机一点s

Vec3 RandomInUnitSphere()
{
Vec3 p;
do {
p = 2.0f * Vec3((rand()%100 / float(100)), (rand() % 100 / float(100)), (rand() % 100 / float(100))) - Vec3(1.0f, 1.0f, 1.0f);
} while (dot(p, p) >= 1.0f);

return p;
}


接着,我们将color方法修改如下:

Vec3 Color(const Ray& r, Hitable *world)
{
hit_record rec;
if (world->hit(r, 0.0, FLT_MAX, rec))
{
Vec3 target = rec.p + rec.normal + RandomInUnitSphere();
//递归,每次吸收50%的能量
return 0.5f*Color(Ray(rec.p, target - rec.p), world);
}
else
{
//绘制背景
Vec3 unit_direction = unit_vector(r.direction());
float t = 0.5f*(unit_direction.y() + 1.0f);
//(1-t)*白色+t*蓝色,结果是一个蓝白的渐变
return (1.0f - t)*Vec3(1.0f, 1.0f, 1.0f) + t*Vec3(0.5f, 0.7f, 1.0f);
}
}


结果如下:



按原文进行一次gamma矫正后:

//获得区域的颜色均值
col /= float(ns);
//gamma矫正
col = Vec3(sqrt(col[0]), sqrt(col[1]), sqrt(col[2]));
int ir = int(255.99*col[0]);
int ig = int(255.99*col[1]);
int ib = int(255.99*col[2]);


结果如下:



这里我稍稍做了一下死,把图像分辨率改为了2000*1000,看一下渲染是什么效果(渲染时间增加了非常多):



球体上可以看出有一些有规律的纹路,现在还不明白为什么。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: