在U3D中实现镜头光晕
发表于2016-03-11
一、简介
镜头光晕本身很简单。绘制一条通过光源和屏幕中心点的直线,然后沿这条直线布置一系列光晕斑,这些光晕斑再进行Blend,这就形成了镜头光晕。如下:
二、淡入淡出
在晴朗的日子里摄像机,如果太阳刚刚偏移出视野边缘仍然会看到光晕,光晕不会在某处突然出现,它是淡入淡出的。所以我们就设计一个“光晕边界”---围绕屏幕边界的区域。如果太阳超出了“屏幕边界”就不会有光晕;如果太阳在边界范围内,就会出现光晕。如下:
那么如何计算太阳在“屏幕边界”上时光晕的强度呢?本文用一种简单快速的方法,如下:
通过包围圆来判断,算法上比较简单,也是比较快速的方法。以下都是在屏幕UV空间中计算的。
小圆的半径r = 0.5 * sqrt(2);
大圆的半径R = r + x; x > 0
Dist = Distance(SunUV,CenterUV); 其中SunUV是太阳在屏幕UV空间的位置,CenterUV是屏幕中心的位置,也就是(0.5,0.5).
Dist归一化: Dist = (Dist – r)/(R – r);
光晕强度 t = LinearInterpolate(1, 0,Dist ); LinearInterpolate是线性插值函数,在1到0之间进行插值。
三、光斑的计算
光斑包括颜色、尺寸、在屏幕上的位置和纹理贴图。如下:
光斑就是沿着这条线(称为光斑分布线)分布的,我们要做的是沿着光斑分布线创建一系列光斑,在U3D里,
U3D提供了GL.Begin(GL.QUADS)这样的API,可以在屏幕空间渲染矩形。如下,创建了4个尺寸位置不一样的光斑:
那怎么计算光斑的位置(也就是A、B、C、D的位置)呢?
四、遮挡
太阳可能被其它物体遮挡,比如远处的建筑物遮挡了太阳,这时候摄像机镜头是没有光晕的,那应该怎么计算这种遮挡关系呢?本文提出一种简单有效的方法:
另外创建一个Camera,我们需要这个Camera渲染场景中的遮挡物体(比如远处的建筑),注意我们是将遮挡物渲染成黑色,
Camera的Background 是白色,得到包含遮挡信息的RTT如下:
我们在太阳的的位置对这遮挡Texture进行采样,
fixed ocllusion = tex2D(_OcllusionTex,v2SunUV ).r;
显然if (ocllusion == 1.0f) 那么太阳没有被遮挡;if (ocllusion == 0.0f) 那么太阳被遮挡。
但是太阳不是一个点,太阳也是有面积的,当太阳被遮挡一部分怎么办?
所以我们对太阳周围的4个点也进行采样:
这种方法只适合类似太阳这样的,因为太阳到摄像机的距离比所有遮挡物到摄像机都远。
如果是场景内的光源,那么就不是渲染黑色的遮挡物了,而是渲染遮挡物的深度图了。
加入GAD的核心用户QQ群:484290331,各类活动奖励任你拿,最新资讯任你读,众多教学任你免费学,如此好地方赶紧加入吧!另VR专属群:476511561,专业VR技术分享,专业导师指导为你答疑解惑,大型小型活动奖励等你拿,免费学习赚奖励的天地,欢迎你加入哟!