标签:water 范围 tps 心得体会 obj ima texture set 深度
如何做一个卡通水面效果
本文参考自教程,加上自己的一点心得体会。
首先,根据水面和场景的深度差异划分为浅水和深水,浅水和深水各取两个极值,然后根据深度进行插值。所谓的浅水,就是水面下的物体与水面的距离较小,颜色较浅;所谓的深水,就是水面下的物体与水面的距离较大,颜色较深。
那么,如何获得场景深度呢?Unity引擎自带了**_CameraDepthTexture**,但这是基于屏幕坐标系的texture,如何在frag shader里去采样到正确的值呢?对于顶点\(v\)而言,我们先通过UnityObjectToClipPos将其转换到齐次坐标系,此时\(v.x\)和\(v.y\)的取值范围均为\([-v.w,v.w]\),然后根据视口变换:
\[
screen.x = (v.x * 0.5 + v.w * 0.5) * screen.width / v.w
\]
\[ screen.y = (v.y * 0.5 + v.w * 0.5) * screen.height / v.w \]
我们发现,实际的采样坐标即为\((screen.x / screen.width, screen.y / screen.height)\)。Unity提供了两个内置函数帮助我们进行采样:ComputeScreenPos和tex2Dproj。ComputeScreenPos这个函数得到的结果为\(((v.x * 0.5 + v.w * 0.5), (v.y * 0.5 + v.w * 0.5), v.z, v.w)\),tex2Dproj函数会对传入的采样坐标进行透视除法再采样。
然而,采样出来的深度值是经过透视投影变换后的深度,已经不再是线性的,我们需要把它还原为原始的深度值再进行使用。这其实本质上是投影变换的逆变换。Unity也提供了一个内置函数:LinearEyeDepth。通过该函数得到原始深度,与水面的原始深度做差,利用这个差异值就可以对颜色进行线性插值了。有两点需要意识到:
综上,以上实现的shader代码如下:
float existDepth01 = tex2Dproj(_CameraDepthTexture, i.screenPos).r;
float existDepth = LinearEyeDepth(existDepth01);
float difference = existDepth - i.screenPos.w;
float difference01 = saturate(difference / _MaxDistanceCutOff);
float4 waterColor = lerp(_ShallowWaterColor, _DeepWaterColor, difference01);
效果如图。
第二步,我们需要为水面加上一些扰动信息,来实现波纹效果。使用一张噪声贴图,直接采样出颜色与现有颜色叠加:
可以发现,由于颜色直接叠加,把大部分区域的颜色刷得太亮了,而我们想要的,其实是亮的地方颜色保持不变,暗的地方刷成波纹的颜色,因此加一个cutoff进行过滤:
接下来,我们希望靠近岸边的边缘部分也要有波纹。靠近岸边的水面和场景的深度差异较小,可以利用这一点降低对噪声的cutoff值,让边缘部分的噪声也可以add到水面上:
另外,可以再加一张扰动贴图,采样两个通道对噪声贴图的uv进行偏移,来实现流动的效果。
现在,大体的感觉已经有了。细心观察可以发现,水面与物体接触的地方,波纹应该更明显一点,也就是与物体接触的地方需要额外降低对噪声的cutoff值。这时,需要借助场景中的法线数据来处理。水面与物体接触的地方法线差异比较大,其他地方法线差异比较小。容易想到用两个法向量的点积来衡量向量的差异程度。
由于Unity自带的法线纹理精确有限,这里考虑自己渲染出一张场景的法线纹理图。额外新建一个camera,通过设置它的depth,使用SetReplacementShader方法,替换掉场景中其他所有shader,让其都用写法线的方式渲染,得到RT。这个方法可以替换掉所有对于Tag相同的shader,让它们用指定的shader渲染,对于Tag不同的,则跳过渲染,这里可以参照Unity官方文档。
接下来,我们可以通过修改shader的tag和blend模式,来让水面变得透明。同时,我们还希望能够调整波纹的颜色。为了让波纹自身的颜色能与水面本身的颜色融合而不是相加,我们采用alpha-blend的模式,让波纹自身的颜色blend到水面上,这时,之前用到的cutoff得到的结果可以用在设置波纹的alpha上。
最后,对波纹边缘处,可以用smoothstep对cutoff进行平滑。
总结一下,实现一个简单的卡通水面效果,分为如下几个步骤:
标签:water 范围 tps 心得体会 obj ima texture set 深度
原文地址:https://www.cnblogs.com/back-to-the-past/p/12483905.html