博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unity Shader 噪声消融特效 - 剑灵死亡特效
阅读量:5096 次
发布时间:2019-06-13

本文共 6225 字,大约阅读时间需要 20 分钟。

噪声是个很神奇的东西,以前接触的时候就是在自动生成地图上,因为噪声本来就近自然所以,很多特效也是基于噪声的。

前几篇文章介绍了纹理和光照,这回其实也就是用这么多。就是光照加一个噪声的法线纹理。

你可能就玩过一款游戏,剑灵,游戏中怪物死亡的时候会有一种消融的效果。让我们来看一看是怎么实现的。

下面三个图片分别是BurnAmount = 0、BurnAmount = 0.25、BurnAmount = 0.5时的效果。

  

这里我们用两个Pass来处理这个效果

  • 第一个Pass:渲染模型的正常颜色和消融的混合颜色
  • 第二个Pass:处理消融的阴影,如不特殊处理则影子不会有消融效果。

下面给出代码(有必要的注释)

1 Shader "Shader/Shader"  2 {  3     Properties  4     {  5         _MainTex ("Main Tex", 2D) = "white" {}  6         // 法线贴图  7         _BumpMap ("Bump Map", 2D) = "bump" {}  8         // 噪声贴图  9         _BurnMap ("Burn Map", 2D) = "white" {} 10         // 控制消融程度 11         _BurnAmount ("Burn Amount", Range(0, 1)) = 0 12         // 控制模型烧焦效果的线宽 13         _LineWidth ("Burn Line Width", Range(0.0, 0.2)) = 0.1 14         // 烧焦边缘的颜色 15         _BurnColor ("Burn Color", Color) = (1, 0, 0, 1) 16     } 17     SubShader 18     { 19         Tags { "RenderType"="Opaque" "Queue"="Geometry" } 20  21         Pass 22         { 23             Tags { "LightMode"="ForwardBase" } 24              25             // 所有面都不被剔除,因为消融的时候应该可以看到物体的内部。 26             Cull Off 27  28             CGPROGRAM 29             #pragma vertex vert 30             #pragma fragment frag 31             // 为得到正确的光照设置的编译指令 32             #pragma multi_compile_fwdbase 33  34             #include "Lighting.cginc" 35             #include "AutoLight.cginc" 36  37             sampler2D _MainTex; 38             sampler2D _BumpMap; 39             sampler2D _BurnMap; 40             float4 _MainTex_ST; 41             float4 _BumpMap_ST; 42             float4 _BurnMap_ST; 43             fixed _BurnAmount; 44             fixed _LineWidth; 45             fixed4 _BurnColor; 46  47             struct a2v 48             { 49                 float4 vertex : POSITION; 50                 float3 normal : NORMAL; 51                 float2 texcoord : TEXCOORD0; 52                 fixed4 tangent : TANGENT; 53             }; 54  55             struct v2f 56             { 57                 float4 pos : SV_POSITION; 58                 float2 uvMainTex : TEXCOORD0; 59                 float2 uvBumpMap : TEXCOORD1; 60                 float2 uvBurnMap : TEXCOORD2; 61                 // 切线视图的光照方向 62                 float3 lightDir : TEXCOORD3; 63                 float3 worldPos : TEXCOORD4; 64                 // Shader 阴影宏:用于对阴影纹理采样的坐标 65                 // 参数:一个可用的差值寄存器的索引值,用世界的顶点坐标。即5(从0开始) 66                 SHADOW_COORDS(5) 67             }; 68  69             v2f vert(a2v v) 70             { 71                 v2f o; 72  73                 o.pos = UnityObjectToClipPos(v.vertex); 74  75                 o.uvMainTex = TRANSFORM_TEX(v.texcoord, _MainTex); 76                 o.uvBumpMap = TRANSFORM_TEX(v.texcoord, _BumpMap); 77                 o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap); 78  79                 TANGENT_SPACE_ROTATION; 80                 o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)); 81                 o.worldPos = UnityObjectToWorldDir(v.vertex); 82  83                 // 阴影宏:在顶点着色器中计算上一步中声明的阴影纹理坐标 84                 TRANSFER_SHADOW(o); 85  86                 return o; 87             } 88  89             fixed4 frag(v2f i) : SV_Target 90             { 91                 // 取噪声贴图进行采样 92                 fixed3 burn = tex2D(_BurnMap, i.uvBurnMap); 93                 // 用于剔除像素点,if (采样结果-消融程度阀值 > 0) 存留 or 丢弃 94                 clip(burn.r - _BurnAmount); 95  96                 fixed3 albedo = tex2D(_MainTex, i.uvMainTex).rgb; 97  98                 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo; 99 100                 fixed3 tangentLightDir = normalize(i.lightDir);101                 fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uvBumpMap));102                 fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentLightDir, tangentNormal));103 104                 // 阴影宏:计算阴影值,最后与漫反射的颜色叠加105                 UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);106 107                 // smoothsetp(e1,e2,x)平滑过度函数108                 // 原理:if (x < e1) 结果 = 0109                 // if (x > e2) 结果 = 1110                 // if (e1 < x < e2) 结果 = 3 * pow(x, 2) - 2 * pow(x, 3)111                 // t = 0时,该像素为正常的模型颜色112                 // t = 1时,该像素位于消融的边界处113                 fixed t = 1 - smoothstep(0.0, _LineWidth, burn.r - _BurnAmount);114 115                 // 最终颜色,在消融和正常中差值,系数为t116                 fixed3 finalColor = lerp(ambient + diffuse * atten, _BurnColor, t);117 118                 return fixed4(finalColor, 1);119             }120             ENDCG121         }122 123         // 此Pass是处理阴影的,我们需要按照正常的Pass的处理来剔除片元或进行顶点动画。以便阴影可以和物体正常渲染的结果相匹配。124         Pass125         {126             // 光照模式定义为阴影127             Tags { "LightMode"="ShadowCaster" }128 129             CGPROGRAM130             #pragma vertex vert131             #pragma fragment frag132             // 处理阴影的编译指令133             #pragma multi_compile_shadowcaster134             135             #include "UnityCG.cginc"136 137             fixed _BurnAmount;138             sampler2D _BurnMap;139             float4 _BurnMap_ST;140 141             struct a2v142             {143                 float4 vertex : POSITION;144                 float2 texcoord : TEXCOORD0;145                 float3 normal : NORMAL;146                 float4 tangent: TANGENT;147             };148 149             struct v2f150             {151                 // 定义阴影投射需要定义的变量152                 V2F_SHADOW_CASTER;153                 float2 uvBurnMap : TEXCOORD0;154             };155             156             v2f vert (a2v v)157             {158                 v2f o;159 160                 // 填充V2F_SHADOW_CASTER定义的变量161                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)162                 o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);163 164                 return o;165             }166             167             fixed4 frag (v2f i) : SV_Target168             {169                 fixed3 burn = tex2D(_BurnMap, i.uvBurnMap);170                 171                 clip(burn - _BurnAmount);172 173                 // 让Unity完成阴影投射174                 SHADOW_CASTER_FRAGMENT(i)175             }176             ENDCG177         }178     }179 }

本文引自Unity Shader 入门精要

转载于:https://www.cnblogs.com/SHOR/p/8044437.html

你可能感兴趣的文章
说说大型高并发高负载网站的系统架构
查看>>
数据结构
查看>>
Linux内核分析07
查看>>
this week,last week,this month,last month
查看>>
输入输出相关命令
查看>>
UNIX网络编程读书笔记:基本TCP套接口编程
查看>>
web.xml 配置中classpath: 与classpath*:的区别
查看>>
kettle-映射控件
查看>>
kettle-Excel输出
查看>>
Java泛型底层源码解析-ArrayList,LinkedList,HashSet和HashMap
查看>>
PNG格式图片(验证码..)不能显示的解决办法
查看>>
[Selenium+Java] Apache ANT with Selenium: Complete Tutorial
查看>>
源码安装mysql数据库
查看>>
UVA11059 - Maximum Product
查看>>
vue-cli webpack 多页面应用配置
查看>>
解读测试架构师
查看>>
10.1 考试 ..........
查看>>
VMware 12 专业版永久许可证密钥
查看>>
PHP 之 MySQL 操作(1)
查看>>
设计模式之装饰者模式-以牛肉面为例
查看>>