学习光线追踪(19)---光源[3]

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.效果

折射和透射效果

这里看起来不是很真实,因为折射和透镜过来的光线没有衰减,所以导致整个结果产生,将不同物体设置反射衰减系数就会好不少。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值