UnityShader——屏幕空间的能量罩(模拟守望先锋温斯顿的能量罩)
来源:互联网 发布:易语言播放音乐源码 编辑:程序博客网 时间:2024/05/04 02:09
前言:
因为是第一次写技术博客可能有些不到位请谅解,废话不多说就先上最终效果图了(PS.可以看出效果图和游戏中还是有差距的,因为Shader刚入门所以有什么不足望指出)。主要的原理是:屏幕空间深度图,纹理动画,遮罩纹理,Blinn-Phong光照模型。(Ps,代码思路主要参考腾讯大神Mya喵神写过的一个的Shader)
所需数学知识:
模型空间到裁剪空间的变换,详情请见冯乐乐的Shader入门到精通4.6.7章节,因为冯乐乐在自己的github上已经放出了第四章的pdf所以这里直接粘一个链接了。
主要的原理:
首先我们要先了解UnityShaderLab中的深度图是如何渲染出来的,在Unity中会直接获取深度缓存或是着色器替换技术,深度图的渲染是需要通过ShadowCaster的Pass来渲染的,也就是说如果没有这个Pass的物体是不会被渲染到深度图中的,而通常透明的物体是没有ShadowCaster这个Pass的(也可以让透明物体有,但是透明物体也会投射阴影),所以只要设置好RenderType(也就是"RenderType"="Transparent"),就可以让我们的能量罩不出现在深度图中,我们可以从下面的图中看出在LinearEyeDepth中的深度图如图所示,深度图中没有出现能量罩(看着是一片黑仔细看,还不行的话再仔细→ →)。
然而只是这样是不够的,我们还可以通过Unity内置的函数o.scrPos = ComputeScreenPos ( o.pos )来得到Clip Space的深度值了,但是需要注意的是Clip Space空间的z值的大小是从-Near至Far的(详情见下图),而深度图中LinearEyeDepth后的范围是Near至Far的,所以我们要再次借助便利的Unity内置函数COMPUTE_EYEDEPTH(o.scrPos.z),来将o.scrPos.z的值转化到Near至Far。
机智的小伙伴应该已经看出来了,在深度图中没有显示出来的能量罩的深度值,却可以通过获取Clip Space的z值来获取,所以我们只要比较这两个值就可以判断出能量罩与别的物体的交汇位置,也就是当深度图中的深度值等于Clip Space的z值的时候是交汇的,于是我们就可以通过这个来做出相交高光的效果了(也就是能量罩与别的物体相交的时候边缘会有蓝白色)。
因为这个文章主要是讲深度图部分,所以纹理动画,Mask和Blinn-Phong就不提了(其实是懒得打字了orz)。
源码:
首先我们需要一个C#脚本来设置相机的深度图模式。
using System.Collections;using System.Collections.Generic;using UnityEngine;public class NewBehaviourScript : MonoBehaviour { private Camera myCamera; public Camera camera { get { if (myCamera == null) { myCamera = GetComponent<Camera>(); } return myCamera; } } void OnEnable() { camera.depthTextureMode |= DepthTextureMode.Depth; } }其次到了我们的主角Shader部分。
Shader "MyShader/XiangJiaoGaoGuang" {Properties {_MainColor ("Color" , Color) = (1,1,1,1)_HighlightColor("HighlightColor" ,Color) = (0,0,1,1)_EdgePow("Threshold" , Range(0 , 5)) = 0.5_RimNum("Rim" , Range(0 , 5)) = 1_MainTex("Main Tex" , 2D) = "white"{}_MaskTex("Mask Tex" , 2D) = "white" {}_speed("Speed" ,Range(0 , 2)) = 1.0}SubShader {Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"}Pass{Tags { "LightMode"="ForwardBase" }Blend One OneZWrite OffCull OffCGPROGRAM#include "UnityCG.cginc"#pragma vertex vert#pragma fragment frag#define UNITY_PASS_FORWARDBASE #pragma multi_compile_fwdbasefloat4 _MainColor;float4 _HighlightColor;sampler2D _CameraDepthTexture;float _EdgePow;sampler2D _MainTex;float4 _MainTex_ST;sampler2D _MaskTex;float _speed;float _RimNum;struct a2v{float4 vertex:POSITION;float3 normal:NORMAL;float2 tex:TEXCOORD0;};struct v2f{float4 pos:POSITION;float4 scrPos:TEXCOORD0;half3 worldNormal:TEXCOORD1;half3 worldViewDir:TEXCOORD2;float2 uv:TEXCOORD3;};v2f vert (a2v v ){v2f o;o.pos = UnityObjectToClipPos ( v.vertex );o.scrPos = ComputeScreenPos ( o.pos );float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; o.worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));o.worldNormal = UnityObjectToWorldNormal(v.normal); o.uv = TRANSFORM_TEX(v.tex , _MainTex);COMPUTE_EYEDEPTH(o.scrPos.z);return o;}fixed4 frag ( v2f i ) : SV_TARGET{//纹理动画和Mask部分,主要作用是实现扫描效果还有六边形图案fixed mainTex = 1 - tex2D(_MainTex , i.uv).a;fixed mask = tex2D(_MaskTex , i.uv + float2(0 , (_Time.y)*_speed)).r;fixed4 finalColor = lerp(_MainColor , _HighlightColor , mainTex);finalColor=lerp(fixed4(0,0,0,1),finalColor,mask);//获取深度图和clip space的深度值float sceneZ = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.scrPos)));float partZ = i.scrPos.z;//diff为比较两个深度值,rim为Phong:在边缘位置加上一层_HighlightColor的颜色 float diff = 1-saturate((sceneZ-i.scrPos.z)*4 - _EdgePow);half rim = pow(1 - abs(dot(normalize(i.worldNormal),normalize(i.worldViewDir))) , _RimNum);//最后通过插值混合颜色finalColor = lerp(finalColor, _HighlightColor, diff);finalColor = lerp(finalColor, _HighlightColor, rim);return finalColor;}ENDCG}}}
源文件:
https://github.com/Porco24/UnityShaderEnergyShield
- UnityShader——屏幕空间的能量罩(模拟守望先锋温斯顿的能量罩)
- 小球的能量损失
- 做个正能量的程序员
- 满满的负能量......
- 做个正能量的程序员
- 自由选择的正能量
- 图像的能量
- 扭曲的空间和扭曲的能量场
- [gdc17]《守望先锋》的EntityComponent架构
- [gdc17]《守望先锋》的EntityComponent架构
- 传播正能量——做一个快乐的程序员
- 【思想感悟】——如何激发自己的正能量
- WEB-QTP随想录—富士康的能量
- 步态能量图的实现(一)
- NOI2010——能量采集(数论)
- 【Get深一度】信号处理(一)——能量信号与功率信号的区别
- 读书笔记(二):逆袭大学——传给IT学子的正能量
- 寂寞的能量开始了
- Numpy学习小结(1)
- 时间复杂度和空间复杂度_增强版
- oracle数据库之约束
- 模拟器安装应用失败(INSTALL_FAILED_NO_MATCHING_ABIS)
- 解决Tomcat不能访问首页的问题,eclipse中tomcat能正常启动
- UnityShader——屏幕空间的能量罩(模拟守望先锋温斯顿的能量罩)
- ffmpeg encode/decode example
- HDU6134(莫比乌斯反演)
- nginx+obs搭建流媒体,实现直播
- 21、多项式插值,最小二乘法和牛顿迭代法
- Android进程间通信(二)- Messenger
- java was started but returned code=13
- 用爬虫来爬取廖老师的python教程的url
- django第一步