学习光线追踪(16)---折射计算[1]

0.简介

前面的反射效果已经和非光追渲染有很大区别了,这回加上折射计算,效果会更好。

1.折射计算

折射计算相对反射要复杂一点,折射公式网上有的是,我就不在这里进行推导和详细讲解了,有需要的可以看下面这篇博客。

光线折射计算

2.添加计算代码

在之前的反射光线附近添加折射光线计算代码,然后折射也进行光追迭代。

光线追踪迭代函数。

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.polygon && 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;*/

	//构造折射光线
	float itea = ((Polygon*)(r.polygon))->m->refract;
	float cosa1 = abs(dot(r.direction ,reflectRayNormal));
	float cosa2 = sqrt(1 - (1 / (itea * itea) * (1 - cosa1 * cosa1)));
	Ray refractRay = Ray(normalize((1 / itea) * r.direction + (cosa1 / itea - cosa2) * reflectRayNormal), r.end.position, 0, vec3(0, 0, 0), nullptr);

	//构造反射光线
	Ray reflectRay = Ray(normalize(r.direction - (2 * dot(r.direction, reflectRayNormal)) * reflectRayNormal), r.end.position, 0, vec3(0, 0, 0), nullptr);
	//获得反射光线方向
	refractRay = rayTrac(refractRay, s, times - 1);
	reflectRay = rayTrac(reflectRay, s, times - 1);
	
	//计算物体返回的颜色
	r = ((Polygon*)(r.polygon))->sample(r, reflectRay, refractRay);
	return r;
}

对于平面有折射的处理代码,球也有,但是之前出了点问题,所以调试了好几次才找到,这里需要注意的是,如果光线进入球体内,那么折射光线会穿过球体,所以要区分光线在球体内发射还是在球外,对于平面,要考虑平面部分正反面,两面都能反光和折射。

Ray Sphere::intersect(Ray ray)
{
	Ray result(ray.direction,ray.position,ray.intensity, vec3(0,0,0), nullptr);
	//计算球和光线的向量
	vec3 v = ray.position - center;
	//如果光源在球体表面或者内部,要专门注意这种情况
	if (abs(length(v) - radius) < 0.001 && dot(normalize(v) , ray.direction) <= 0)
	{
		result.polygon = this;	
		float cosa = glm::dot(normalize((center - ray.position)), normalize(ray.direction));//normalize(abs((center - ray.position))*normalize(ray.direction));
		result.distance = 2 * radius * abs(cosa);
		result.end = ray.getEndPoint(result.distance);
		result.normal = -normalize(result.end.position - center);
		return result;
	}
	float disSubR = dot(v , v) - (radius * radius);
	float ray_v_dot = dot(ray.direction , v);

	if (ray_v_dot <= 0)
	{
		float discr = ray_v_dot * ray_v_dot - disSubR;
		if (discr >= 0)
		{
			result.polygon = this;
			result.distance = -ray_v_dot - sqrt(discr);
			result.end = ray.getEndPoint(result.distance);
			result.normal = normalize(result.end.position - center);
			return result;
		}
	}
	return result;
}

3.效果

折射效果

4.源码

release0.11

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值