简介

游戏中经常会看到特效给人眼前一亮的感觉,例如当怪物死亡时逐渐消逝的效果、人物由隐形状态逐渐显形的效果。本篇文章将从Shader的角度去思考如何通过代码去实现这些效果。

原理

  • 噪声图:利用噪声图的特性可以产生从随机点开始扩散的消融效果
  • 片元裁剪:利用Clip函数裁剪消融片元
    基本流程:定义一个阈值(DissolveThreshold)范围在[0,1],对噪声图进行纹理采样,将采样结果与阈值进行比较,如果大于阈值则正常显示,如果小于阈值则裁剪当前片元。当阈值从0递增到1时,消融范围逐步扩大实现逐渐消逝效果。当阈值从1递减到0时,消融范围逐步减少实现逐渐显形效果。

普通消融效果

Shader"MyShader/NormalDissolve"
{Properties{_Diffuse("Diffuse Color",Color) = (1,1,1,1)                      //主颜色_MainTex("Main Tex",2D) = "white"{}                               //主纹理_DissolveMap("Dissolve Map",2D) = "white"{}                       //消融噪声_DissolveThreshold("Dissolve Threshold",Range(0.0,1.0)) = 0.0  //阈值}SubShader{Tags{"RenderType" = "Opaque""Queue" = "Geometry"}//主Pass负责消融效果Pass{Tags{"LightMode"="ForwardBase"}//关闭背面剔除同时渲染模型正面与背面(避免消融裸露模型内部)Cull OffCGPROGRAM#include"Lighting.cginc"#include"AutoLight.cginc"#pragma multi_compile_fwdbase#pragma vertex vert#pragma fragment fragfixed4 _Diffuse;sampler2D _MainTex;float4 _MainTex_ST;sampler2D _DissolveMap;float4 _DissolveMap_ST;float _DissolveThreshold;struct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float4 texcoord : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float2 uvMainTex : TEXCOORD0;float2 uvMapTex : TEXCOORD1;float3 worldNormal : TEXCOORD2;};v2f vert(a2v v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uvMainTex = TRANSFORM_TEX(v.texcoord,_MainTex);o.uvMapTex = TRANSFORM_TEX(v.texcoord,_DissolveMap);o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);return o;}fixed4 frag(v2f i) : SV_Target{//采样噪声纹理fixed3 map = tex2D(_DissolveMap,i.uvMapTex).rgb;//阈值比较进行裁剪clip(map.r-_DissolveThreshold);fixed3 worldNormal = normalize(i.worldNormal);fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);fixed3 albedo = tex2D(_MainTex,i.uvMainTex).rgb;fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;fixed3 diffuse = _Diffuse.rgb*_LightColor0.rgb*(dot(worldNormal,worldLight)*0.5+0.5);return fixed4(diffuse,1);}ENDCG}//负责处理阴影(避免以消融的片元产生阴影进而穿帮)Pass{Tags{"LightMode" = "ShadowCaster"}CGPROGRAM#include "UnityCG.cginc"#pragma vertex vert#pragma fragment frag#pragma multi_compile_shadowcasterfloat _DissolveThreshold;sampler2D _DissolveMap;float4 _DissolveMap_ST;struct v2f{V2F_SHADOW_CASTER;float2    uvDissolveMap : TEXCOORD0;};v2f vert(appdata_base v){v2f o;TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);o.uvDissolveMap = TRANSFORM_TEX(v.texcoord,_DissolveMap);return o;}fixed4 frag(v2f i) : SV_Target{fixed3 map = tex2D(_DissolveMap,i.uvDissolveMap).rgb;clip(map.r-_DissolveThreshold);SHADOW_CASTER_FRAGMENT(i);}ENDCG}}FallBack"Diffuse"
}

从运行效果图可以看出消融效果比较突兀,没有过渡的感觉。例如像物体燃烧时逐渐碳化然后消融的效果无法达到。

渐变消融效果

基本思路:定义一个边界宽度来控制渐变的范围,通过smoothstep函数根据噪声图采样结果与阈值的相减值计算渐变系数,根据渐变系数通过插值函数得到渐变色,将渐变色与片元颜色进行混合输出最终表面颜色值。

Shader"MyShader/GradientDissolve"
{Properties{_Diffuse("Diffuse Color",Color) = (1,1,1,1)                      //主颜色_MainTex("Main Tex",2D) = "white"{}                               //主纹理_DissolveMap("Dissolve Map",2D) = "white"{}                       //消融噪声_DissolveThreshold("Dissolve Threshold",Range(0.0,1.0)) = 0.0  //阈值_DissolveEdge("Dissolve Edge Width",Range(0.0,0.2)) = 0.1        //渐变边界宽度_DissolveColorA("Dissolve Color A",Color) = (1,1,1,1)            //边界颜色(近)_DissolveColorB("Dissolve Color B",Color) = (1,1,1,1)         //边界颜色(远)}SubShader{Tags{"RenderType" = "Opaque""Queue" = "Geometry"}//主Pass负责消融效果Pass{Tags{"LightMode"="ForwardBase"}//关闭背面剔除同时渲染模型正面与背面(避免消融裸露模型内部)Cull OffCGPROGRAM#include"Lighting.cginc"#include"AutoLight.cginc"#pragma multi_compile_fwdbase#pragma vertex vert#pragma fragment fragfixed4 _Diffuse;sampler2D _MainTex;float4 _MainTex_ST;sampler2D _DissolveMap;float4 _DissolveMap_ST;float _DissolveThreshold;float _DissolveEdge;fixed4 _DissolveColorA;fixed4 _DissolveColorB;struct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float4 texcoord : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float2 uvMainTex : TEXCOORD0;float2 uvMapTex : TEXCOORD1;float3 worldNormal : TEXCOORD2;};v2f vert(a2v v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uvMainTex = TRANSFORM_TEX(v.texcoord,_MainTex);o.uvMapTex = TRANSFORM_TEX(v.texcoord,_DissolveMap);o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);return o;}fixed4 frag(v2f i) : SV_Target{fixed3 map = tex2D(_DissolveMap,i.uvMapTex).rgb;clip(map.r-_DissolveThreshold);fixed3 worldNormal = normalize(i.worldNormal);fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);fixed3 albedo = tex2D(_MainTex,i.uvMainTex).rgb;fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;fixed3 diffuse = _Diffuse.rgb*_LightColor0.rgb*(dot(worldNormal,worldLight)*0.5+0.5);/*smoothstep(edge0,edge1,x)函数:当x<=edge0时:返回0当edge0<=x<=edge1时:返回edge0与edge1间平滑插值当x>=edge0时:返回1*///计算渐变系数fixed t = 1-smoothstep(0.0,_DissolveEdge,map.r-_DissolveThreshold);//计算渐变颜色fixed3 burnColor = lerp(_DissolveColorA,_DissolveColorB,t);burnColor = pow(burnColor,5);//颜色混合fixed3 finalColor = lerp(ambient + diffuse,burnColor,t*step(0.0001,_DissolveThreshold));return fixed4(finalColor,1);}ENDCG}//负责处理阴影Pass{Tags{"LightMode" = "ShadowCaster"}CGPROGRAM#include "UnityCG.cginc"#pragma vertex vert#pragma fragment frag#pragma multi_compile_shadowcasterfloat _DissolveThreshold;sampler2D _DissolveMap;float4 _DissolveMap_ST;struct v2f{V2F_SHADOW_CASTER;float2   uvDissolveMap : TEXCOORD0;};v2f vert(appdata_base v){v2f o;TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);o.uvDissolveMap = TRANSFORM_TEX(v.texcoord,_DissolveMap);return o;}fixed4 frag(v2f i) : SV_Target{fixed3 map = tex2D(_DissolveMap,i.uvDissolveMap).rgb;clip(map.r-_DissolveThreshold);SHADOW_CASTER_FRAGMENT(i);}ENDCG}}FallBack"Diffuse"
}

Shader之消融效果相关推荐

  1. Unity3d shader实现消融效果

    实现原理:噪声纹理+透明度测试 噪声纹理: 在我的理解下就是,存储着随机值的一张纹理图片,因为大量生成随机数非常的耗时而且麻烦,如果用一张图来存储随机值,这样获取起来会非常的简单高效,利用噪声纹理我们 ...

  2. Unity Shader 燃烧消融效果(surface表面着色器)

    有些时候需要让角色死亡时逐渐燃烧消失,用表面着色器很容易实现. 可以用一张黑白图片控制各部位的消融顺序,比如让该图片的某通道和一个变量相比,小于该变量则舍弃片元.变量从0不断变大,则消融面积逐渐扩大. ...

  3. 【Unity Shader 消融效果_案例分享】

    1.实现逻辑 消融效果主要是利用了Shader中的clip()函数,也就是透明测试功能,在ASE中叫"Opacity Mask". 消融效果是基于一张"Noise&quo ...

  4. Unity Shader学习:Dissolve消融效果

    Unity Shader学习:Dissolve消融效果 消融效果在游戏里非常常用,这里简单的实现下,代码里用到了if分支在shader里可能会费一点,如果想直接用puppet_master大佬版本的话 ...

  5. Shader学习的基础知识( 三十)消融效果

    消融效果其实就是噪声纹理+透明度测试,取样阈值在小于0则裁剪掉,0到N显示中间色,N到1则正常显示. Shader "Unity Shaders Book/Chapter 15/Dissol ...

  6. Unity_Shader高级篇_15_Unity Shader入门精要_消融效果

    第15章 使用噪音 很多时候,向规则的事物里添加一些"杂乱无章"的效果往往会有意想不到的效果.而这些"杂乱无章"的效果来源就是噪音.在本章中,我们将会学习如何使 ...

  7. UnityShader入门精要——消融效果

    消融效果 原理:噪声纹理+透明度测试 使用噪声纹理采样的结果和某个控制消融程度的阈值比较,如果小于阈值,就使用clip函数把它对应的像素裁剪掉,这些部分就对应了图中被"烧毁"的区域 ...

  8. 练习项目(二):消融效果

    概述 本篇是"练习项目"系列的第二篇,主要介绍一下利用消融实现的效果.在游戏开发的过程中,有很多看起来很神奇的效果,都是使用消融的原理实现的. 原理 主要的原理,就是使用噪声图和透 ...

  9. 使用OpenGL Shader实现放大镜效果

    使用OpenGL Shader实现放大镜效果 2014年3月16日renjihe发表评论阅读评论 周末闲来无事,想玩玩OpenGL Shader,想想就实现一个放大镜效果的Shader吧. 着色器可以 ...

最新文章

  1. Multithread 之 introduction
  2. Spring 4 使用Freemarker模板发送邮件添加附件
  3. ubuntu 安装php-redis
  4. The proof of “chi-square statistics follows chi-square distribution”
  5. 数学--数论--POJ281(线性同余方程)
  6. 理解 LruCache 机制
  7. 基于android的电影院订票影院售票系统app
  8. ElasticSearch从入门到精通:Logstash妙用
  9. 简单工厂模式学习总结
  10. 2017 上海车牌(沪牌)标书购买攻略
  11. Nginx与Zuul的区别
  12. 量子计算机epr,从EPR到量子信息[转] - 物理 - 小木虫 - 学术 科研 互动社区
  13. Specular Highlights(镜面光)
  14. 计算机solidwork实训报告,SolidWorks实训报告.doc
  15. Zabbix 监控之项目类型-Trapper
  16. 【统计计算】关于Jackknife的理解和推导
  17. 【数据读写】csv文件与xls/xlsx文件
  18. 抖音短视频编辑工具EffectCreator 6.4.0中文版
  19. 关于spring与EHcache的集成
  20. 苹果官网产品展示特效

热门文章

  1. 在甲骨文云容器实例(Container Instances)上部署Oracle Linux 7 Desktop
  2. Flip Gamedfs
  3. Python 爬取今日头条的图片新闻
  4. PNAS:青少年大脑功能连接的保守和破坏性模式变化
  5. 一位逝去的华为青年胡新宇:天堂里不再有加班
  6. “金九银十”是找工作的最佳时期吗?那倒未必
  7. QUI的开工 -- 打造一个简单实用的UI库 , 征集LOGO
  8. 【技法操作】PS制作日历图标,UI设计教程
  9. HAUT OJ 1508 zp与车费
  10. maven打jar包