0.简介
这次实现以下反射效果,这里开始就涉及光线追踪原理了。
1.反射
光线反射,要经过多个物体反射,这里我们使用光线追踪方法,追踪折射光线。
Ray rayTrac(Ray ray,vector<Polygon*> s,int times)
{
Ray r(vec3(0,0,0),vec3(0,0,0),0,vec3(0,0,0),nullptr);
if (times <= 0)
return r;
float minDistance= FLT_MAX;
for (auto obj : s)
{
//找到最近的物体
Ray rayTemp = obj->intersect(ray);
if (rayTemp.distance < minDistance )
{
minDistance = rayTemp.distance;
r = rayTemp;
}
}
if (r.polygon == nullptr)
return Ray(vec3(0, 0, 0), vec3(0, 0, 0), 0, vec3(0, 0, 0), nullptr);
//计算反射光线
vec3 reflectRayNormal = r.normal;
//if (dot(r.direction , reflectRayNormal) > 0)
// reflectRayNormal = -reflectRayNormal;
//构造反射光线
Ray reflectRay = Ray(normalize(r.direction - (2 * dot(r.direction, reflectRayNormal)) * reflectRayNormal),r.end,0,vec3(0,0,0),nullptr);
//获得反射光线方向
reflectRay = rayTrac(reflectRay,s,times-1);
//计算物体返回的颜色
r = ((Polygon*)(r.polygon))->sample(r, reflectRay ,r);
return r;
}
这个函数会追踪3次折射光线,开始先找到从逆向光线出发的位置,这里和之前说的光线都是逆向的光线,找到逆向光线打到的最近的物体,然后计算这个物体上的反射光线。反射光线比较好计算,已知逆向入射光线,和法向量,就可以求得逆向的反射光线,应该不难,下面我把原理图画一下。
所以反射光线就是这样计算
计算好反射光线后,就要对反射光线进行追踪,就是递归追踪函数,这里递归了3层。然后将反射光线的结果输入到颜色采样中计算。
Ray Polygon::sample(Ray out, Ray reflect, Ray refract)
{
Ray res(out.direction, out.position, 0, vec3(0, 0, 0), out.polygon);
float cosa = dot(out.normal ,normalize(-out.direction));//光线入射角和面法向量的cos值
//发光计算
res.color += m.color * m.light * std::fmaxf(cosa,0);
//反射颜色计算
res.color += reflect.color * m.specular;
return res;
}
这样一来就支持了反射计算,放一张图看效果。
可以看到,蓝色球上面反射了黄色球,黄色球上面反射了蓝色球,因为反射次数有限,所以不会无限反射下去。
2.下一步
光是球没什么意思,下一步加上平面看看效果。