Shader之消融效果
简介
游戏中经常会看到特效给人眼前一亮的感觉,例如当怪物死亡时逐渐消逝的效果、人物由隐形状态逐渐显形的效果。本篇文章将从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之消融效果相关推荐
- Unity3d shader实现消融效果
实现原理:噪声纹理+透明度测试 噪声纹理: 在我的理解下就是,存储着随机值的一张纹理图片,因为大量生成随机数非常的耗时而且麻烦,如果用一张图来存储随机值,这样获取起来会非常的简单高效,利用噪声纹理我们 ...
- Unity Shader 燃烧消融效果(surface表面着色器)
有些时候需要让角色死亡时逐渐燃烧消失,用表面着色器很容易实现. 可以用一张黑白图片控制各部位的消融顺序,比如让该图片的某通道和一个变量相比,小于该变量则舍弃片元.变量从0不断变大,则消融面积逐渐扩大. ...
- 【Unity Shader 消融效果_案例分享】
1.实现逻辑 消融效果主要是利用了Shader中的clip()函数,也就是透明测试功能,在ASE中叫"Opacity Mask". 消融效果是基于一张"Noise&quo ...
- Unity Shader学习:Dissolve消融效果
Unity Shader学习:Dissolve消融效果 消融效果在游戏里非常常用,这里简单的实现下,代码里用到了if分支在shader里可能会费一点,如果想直接用puppet_master大佬版本的话 ...
- Shader学习的基础知识( 三十)消融效果
消融效果其实就是噪声纹理+透明度测试,取样阈值在小于0则裁剪掉,0到N显示中间色,N到1则正常显示. Shader "Unity Shaders Book/Chapter 15/Dissol ...
- Unity_Shader高级篇_15_Unity Shader入门精要_消融效果
第15章 使用噪音 很多时候,向规则的事物里添加一些"杂乱无章"的效果往往会有意想不到的效果.而这些"杂乱无章"的效果来源就是噪音.在本章中,我们将会学习如何使 ...
- UnityShader入门精要——消融效果
消融效果 原理:噪声纹理+透明度测试 使用噪声纹理采样的结果和某个控制消融程度的阈值比较,如果小于阈值,就使用clip函数把它对应的像素裁剪掉,这些部分就对应了图中被"烧毁"的区域 ...
- 练习项目(二):消融效果
概述 本篇是"练习项目"系列的第二篇,主要介绍一下利用消融实现的效果.在游戏开发的过程中,有很多看起来很神奇的效果,都是使用消融的原理实现的. 原理 主要的原理,就是使用噪声图和透 ...
- 使用OpenGL Shader实现放大镜效果
使用OpenGL Shader实现放大镜效果 2014年3月16日renjihe发表评论阅读评论 周末闲来无事,想玩玩OpenGL Shader,想想就实现一个放大镜效果的Shader吧. 着色器可以 ...
最新文章
- Multithread 之 introduction
- Spring 4 使用Freemarker模板发送邮件添加附件
- ubuntu 安装php-redis
- The proof of “chi-square statistics follows chi-square distribution”
- 数学--数论--POJ281(线性同余方程)
- 理解 LruCache 机制
- 基于android的电影院订票影院售票系统app
- ElasticSearch从入门到精通:Logstash妙用
- 简单工厂模式学习总结
- 2017 上海车牌(沪牌)标书购买攻略
- Nginx与Zuul的区别
- 量子计算机epr,从EPR到量子信息[转] - 物理 - 小木虫 - 学术 科研 互动社区
- Specular Highlights(镜面光)
- 计算机solidwork实训报告,SolidWorks实训报告.doc
- Zabbix 监控之项目类型-Trapper
- 【统计计算】关于Jackknife的理解和推导
- 【数据读写】csv文件与xls/xlsx文件
- 抖音短视频编辑工具EffectCreator 6.4.0中文版
- 关于spring与EHcache的集成
- 苹果官网产品展示特效