【UnityShader】屏幕空间全息扫描效果
2017-10-28 21:49
330 查看
前段时间刚玩《使命召唤11》的时候发现里面新增了一种很高科技的扫描手榴弹,可以产生一圈类似全息效果的扫描圈,并显示出墙后的敌人,类似这样:
![](http://img.blog.csdn.net/20171028214901935?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbW9iaWxlYmJraTM5OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
最近打算实现一个用在第三人称中类似的效果,如下:
![](http://www.lsngo.net/wp-content/uploads/2017/10/scan.gif)
实现方案:
1.根据_CameraDepthTexture计算屏幕空间像素点的世界坐标
2.将扫描发起位置的世界坐标传入shader
3.计算屏幕空间世界坐标到扫描发起位置世界坐标的距离
4.根据相关参数渲染出扫描区域
1._CameraDepthTexture中记录了投影空间的深度信息,通过如下方式可以得到世界坐标:
2.计算传入的初始位置和屏幕空间世界坐标距离:
![](http://img.blog.csdn.net/20171028215243057?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbW9iaWxlYmJraTM5OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
3.保存上一步的渲染结果,使用CommandBuffer,将需要标记为持续显示的目标(例如敌人)也渲染到该纹理,注意需要判断目标是否在摄像机内,效果如下:
![](http://img.blog.csdn.net/20171028220604385?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbW9iaWxlYmJraTM5OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
public static void CallRender(Vector3 worldPosition, Renderer[] renderer)
{
if (!IsInitialized())
return;
if (instance.m_IsShowingEffect)
{
if (renderer == null)
return;
Vector3 pjpos = instance.m_Camera.worldToCameraMatrix.MultiplyPoint(worldPosition);
pjpos = instance.m_Camera.projectionMatrix.MultiplyPoint(pjpos);
if (pjpos.x < -1 || pjpos.x > 1 || pjpos.y < -1 || pjpos.y > 1 || pjpos.z < -1 || pjpos.z > 1)
return;
for (int i = 0; i < renderer.Length; i++)
{
instance.m_CommandBuffer.DrawRenderer(renderer[i], instance.m_ReplaceMaterial);
}
}
}
4.根据屏幕uv信息将屏幕uv栅格化,并计算每个格子中采样到的颜色值,可以得到如下结果:
![](http://img.blog.csdn.net/20171028215318014?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbW9iaWxlYmJraTM5OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
5.同样根据刚刚栅格的结果,可以计算出每一小格的uv,根据该uv来采样用于作为全息扫描效果的纹理,得到如下结果:
![](http://img.blog.csdn.net/20171028215409880?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbW9iaWxlYmJraTM5OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
6.叠加最终结果:
![](http://img.blog.csdn.net/20171028215444536?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbW9iaWxlYmJraTM5OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
Git地址请点击博客原文
最近打算实现一个用在第三人称中类似的效果,如下:
![](http://www.lsngo.net/wp-content/uploads/2017/10/scan.gif)
实现方案:
1.根据_CameraDepthTexture计算屏幕空间像素点的世界坐标
2.将扫描发起位置的世界坐标传入shader
3.计算屏幕空间世界坐标到扫描发起位置世界坐标的距离
4.根据相关参数渲染出扫描区域
1._CameraDepthTexture中记录了投影空间的深度信息,通过如下方式可以得到世界坐标:
fixed depth = tex2D(_CameraDepthTexture, i.uv).r; fixed4 projPos = fixed4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, -depth * 2 + 1, 1); worldPos = mul(internalCameraToWorld, worldPos); worldPos /= worldPos.w;
2.计算传入的初始位置和屏幕空间世界坐标距离:
fixed dis = length(internalCentPos.xyz - worldPos.xyz); fixed a = 1 - saturate((abs(dis - internalArg.x) - internalArg.y) / internalArg.z); a = a * internalFade.x + c * internalFade.y;最终可以得到如下效果:
3.保存上一步的渲染结果,使用CommandBuffer,将需要标记为持续显示的目标(例如敌人)也渲染到该纹理,注意需要判断目标是否在摄像机内,效果如下:
public static void CallRender(Vector3 worldPosition, Renderer[] renderer)
{
if (!IsInitialized())
return;
if (instance.m_IsShowingEffect)
{
if (renderer == null)
return;
Vector3 pjpos = instance.m_Camera.worldToCameraMatrix.MultiplyPoint(worldPosition);
pjpos = instance.m_Camera.projectionMatrix.MultiplyPoint(pjpos);
if (pjpos.x < -1 || pjpos.x > 1 || pjpos.y < -1 || pjpos.y > 1 || pjpos.z < -1 || pjpos.z > 1)
return;
for (int i = 0; i < renderer.Length; i++)
{
instance.m_CommandBuffer.DrawRenderer(renderer[i], instance.m_ReplaceMaterial);
}
}
}
4.根据屏幕uv信息将屏幕uv栅格化,并计算每个格子中采样到的颜色值,可以得到如下结果:
float2 fl = floor(i.uv * _EffectScale); float dp = tex2D(_PreTex, (fl + float2(0.5, 0.5)) / _EffectScale); float4 led = tex2D(_EffectTex, i.uv * _EffectScale - fl); col.rgb += led.rgb*dp;
5.同样根据刚刚栅格的结果,可以计算出每一小格的uv,根据该uv来采样用于作为全息扫描效果的纹理,得到如下结果:
6.叠加最终结果:
Git地址请点击博客原文
相关文章推荐
- 基于GPU屏幕空间的精确光学折射效果
- Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果
- 仿微信二维码扫描中间透明效果
- 【Android】滑动屏幕效果GestureDetector、OnGestureListener、ViewFlipper
- OpenGL 画出雷达动态扫描效果(二) 非底图
- 【2013-09-10 09:52 星期二 Android动画------ 模拟电视机关闭屏幕效果】
- Android利用ViewFlipper实现屏幕切换动画效果
- Unity 屏幕震动效果实现
- GIS地理信息系统中的空间地理坐标与屏幕坐标的对应关系
- Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
- 360手机卫士---扫描杀雷达效果
- 微信二维码扫描时的动画效果 线
- Android动画之雷达扫描效果
- Android:基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
- QT实现屏幕滑动效果窗体
- 移动端开发中是不是你如何给webview设置适配屏幕都没效果,可能是这种原因
- Unity屏幕震动效果
- Unity shader学习之屏幕后期处理效果之运动模糊
- Unity Shader-后处理:屏幕水波效果
- PopupWindow小坑:无论偏移多大,不会跑出屏幕。 充满显示上方空间