URP - 深度贴花效果实现
一、实现思路
- 采样深度图并将深度图中的深度信息转换到视图空间
- 求出应用了深度贴花Shader的对象在视图空间中的坐标(例如立方体)
- 重建贴花在视图空间下的坐标,使贴花的位置信息更换为立方体在场景中投影后的坐标(不清楚这样表述对不对,请大佬指正)重建贴花的视图空间坐标能够利用这些深度信息,准确地将贴花放置在场景中正确的深度位置上,使得贴花看起来像是融入到了场景中的物体表面,而不是漂浮在表面之上或之下,从而实现真实的贴花效果。
- 将视图空间下的坐标转换到世界空间坐标系下
- 再将坐标信息由世界空间转换到对应模型的坐标系下,这样可以动态调整贴花的位置、旋转和缩放
其实我也没有太理解这种方法的具体原理,只清楚了些大概,这种方法应该是基于世界空间的深度贴花,使用AI查了一下大概的实现原理
二、具体的实现方法
1. 采样深度图并将深度图中的深度信息转换到视图空间
- 声明深度图
TEXTURE2D(_CameraDepthTexture);
SAMPLER(sampler_CameraDepthTexture);
- 利用模型在屏幕空间下的坐标采样深度图并将深度值转换到视图空间
float2 screenUV = i.positionCS / _ScreenParams.xy;
float depthTex = SAMPLE_TEXTURE2D(_CameraDepthTexture,sampler_CameraDepthTexture,screenUV);
float depthZ = LinearEyeDepth(depthTex,_ZBufferParams);
2. 求应用了深度贴花Shader的对象在视图空间中的坐标(例如立方体)
//将模型顶点的本地空间坐标转换为世界空间下的坐标
float3 positionWS = TransformObjectToWorld(v.positionOS);
//将模型顶点的世界空间坐标转换为视图空间下的坐标
o.positionVS = TransformWorldToView(positionWS);
3. 重建贴花在视图空间下的坐标(后续使用此坐标转换到模型空间下的坐标来采样贴花纹理)
float4 depthVS = 1;
//Z值为深度图在视图空间下的值
depthVS.z = depthZ;//XY方向的值根据贴花模型与场景中物体的透视关系求出
depthVS.xy = i.positionVS.xy * depthZ / -i.positionVS.z;
俺实在不太明白为什么要这样子计算xy方向的值
4. 将重建贴花在视图空间下的坐标转换到世界空间下
//将深度图中的像素在视图空间下的坐标值转换到世界空间下
float3 depthWS = mul(unity_CameraToWorld,depthVS);
5. 再将世界空间下的坐标转换到模型空间
float3 depthOS = mul(unity_WorldToObject,float4(depthWS,1));
6. 利用此坐标作为UV值采样贴花纹理(若应用贴花纹理的对象为立方体,就使用X和Z方向的值)
float2 uv = depthOS.xz+0.5;
float4 mainTex = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,uv);
但是我有个疑惑,为什么这样做出来的效果不是很对呢?在贴花移动到摄像机的远处时,贴花的半个部分就不显示了是为什么?
【太妃糖耶】最新视频来袭,快来看看吧!