0.简介
目前,还有个问题没有解决,就是在场景中,所有光线的反射折射都对其余物体有影响,这些影响可以考虑处理。
1.反射折射
比如一个光源照到了镜面反射物体,那么此时镜面反射物体就相当于一个光源,再次对其余物体反射光线,此时,这类反射物体就可以被认为是一个光源,透镜并不只是对光源方向产生折射效果,对任何方向都有,只是因为有光照一面光线强,导致阴影产生,别的方向没有强光源,所以看不出来有阴影效果,但是实际上各个方向都有阴影的,也都有折射后投影效果的,只是不明显而已。所以要对每个物体再设置一个光线吸收系数。
2.实现
这次将反射和折射物体当做光源去处理了。
vector<Ray> findLights(vector<Polygon*> s,Ray & r,int times)
{
vector<Ray> lightsRay;
for (auto obj : s)
{
Ray lightRay;
//能发光的话,单个物体
if (obj->m != nullptr && (obj->m->light > 0.0f))
{
if (((Polygon*)(r.polygon))->m != nullptr && ((Polygon*)(r.polygon))->m->light > 0 && (r.polygon != obj))
break;
//获取光源上随机一点
vec3 point = obj->getLightCenter();
//构造光线,光源与当前物体的直接连线
lightRay = Ray(normalize(point - r.end.position), r.end.position, r.intensity, r.color, nullptr);
//计算光碰撞的物体,
lightRay = findMinDistanceRay(s, lightRay);
//如果物体是直接对着光源,获取光源的信息
if (lightRay.polygon == obj)
lightsRay.push_back(lightRay);
else
{
//这里是处理阴影部分,如果是透明材质的阴影,则继续计算
if (lightRay.polygon != nullptr && ((Polygon*)(lightRay.polygon))->m != nullptr && ((Polygon*)(lightRay.polygon))->m->transparent > 0)
{
Ray tranRay;
int count = 0;
//如果自身是透镜就不用计算了
for (int j = 0; j < 2 && lightRay.polygon != r.polygon; j++)
{
//获取光源上随机一点
vec3 point = ((Polygon*)(lightRay.polygon))->getRandomPoint();
//构造光线,光源与当前物体的直接连线
tranRay = Ray(normalize(point - r.end.position), r.end.position, r.intensity, r.color, nullptr);
//计算光碰撞的颜色,
tranRay = findMinDistanceRay(s, tranRay);
//如果物体是直接对着透明物体,累计光线结果
//上面的条件是如果物体与光源之间有其他物体遮挡,并且这个遮挡物体还是透明物体的时候
//由于前面计算的是与光源中心的方向,所以当计算此物体与中间透明物体之间是否有其余物体的时候,是有可能有别的物体
//因为光线方向不同了
if (lightRay.polygon == tranRay.polygon)
{
Ray rt = rayTrac(tranRay, s, times);
lightRay.intensity += rt.intensity;
lightRay.color += rt.color;
count++;
}
}
if (count != 0)
{
lightRay.intensity /= count;
lightRay.color /= (count * 1.0f);
lightsRay.push_back(lightRay);
}
}
}
}
//如果是透镜则进行光线追踪
else if (obj->m != nullptr && (obj->m->specular > 0.0f|| obj->m->transparent>0))
{
Ray tranRay;
int count = 0;
float intensity = 0;
vec3 color = vec3(0,0,0);
//如果自身是透镜就不用计算了
for (int j = 0; j < 2 && obj != r.polygon; j++)
{
//获取光源上随机一点
vec3 point = obj->getRandomPoint();
//构造光线,光源与当前物体的直接连线
tranRay = Ray(normalize(point - r.end.position), r.end.position, r.intensity, r.color, nullptr);
//计算光碰撞的颜色,
tranRay = findMinDistanceRay(s, tranRay);
//是透明物体本身就累加
if (*obj == tranRay.polygon)
{
Ray rt = rayTrac(tranRay, s, times);
//lightsRay.push_back(rt);
intensity += rt.intensity;
color += rt.color;
count++;
}
}
if (count != 0)
{
lightRay = tranRay;
lightRay.intensity = intensity/count;
lightRay.color = color/(count * 1.0f);
lightsRay.push_back(lightRay);
}
}
}
return lightsRay;
}
将光源计算独立成了一个函数,这里需要多次采样,我大概计算了200次然后得到了一个结果。
3.效果
折射和透射效果
这里看起来不是很真实,因为折射和透镜过来的光线没有衰减,所以导致整个结果产生,将不同物体设置反射衰减系数就会好不少。