Shader消融特效

角色死亡消融,尸体消融,地图烧毁特效
不带阴影
参考 《unity shader 入门精要》

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Book/15.Dissolve" {
    Properties {
        _BurnAmount("Burn Amount",Range(0.0,1.0)) = 0.0
		_LineWidth("Burn Line Width",Range(0.0,0.2))=0.1
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
		_BumpMap("Bump Map",2D)= "white" {}
		_BurnFirstColor("Burn First Color",Color)= (1,0,0,1)
		_BurnSecondColor("Burn Second Color",Color)= (1,0,0,1)
		_BurnMap("Burn Map",2D)= "white" {}
    }
    SubShader {
        Tags {"RenderType"="Opaque" "Queue"="Geometry"}
        

	Pass {
		Tags {"LightMode"="ForwardBase" }
		Cull Off


        CGPROGRAM
        #include "UnityCG.cginc"
		#include "Lighting.cginc"
		#include "AutoLight.cginc"

		#pragma multi_compile_fwdbase
        #pragma vertex vert
        #pragma fragment frag



			sampler2D _MainTex;
            sampler2D _BurnMap;
            sampler2D _BumpMap;
            float4 _BurnFirstColor;
            float4 _BurnSecondColor;
            float4 _MainTex_ST;
            float4 _BumpMap_ST;
            float4 _BurnMap_ST;
            float _BurnAmount,_LineWidth;

            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float2 uvMainTex : TEXCOORD0;
                float2 uvBumpMap : TEXCOORD1;
                float2 uvBurnMap : TEXCOORD2;
                float3 lightDir  : TEXCOORD3;
                float3 worldPos  : TEXCOORD4;
                SHADOW_COORDS(5)
			};

            v2f vert( a2v v ) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				//o.uvMainTex = v.texcoord*_MainTex_ST.xy + _MainTex_ST.zw;
				o.uvMainTex = TRANSFORM_TEX( v.texcoord,_MainTex);
				 o.uvBumpMap = TRANSFORM_TEX( v.texcoord,_BumpMap);
				 o.uvBurnMap = TRANSFORM_TEX( v.texcoord,_BurnMap);
				 //副切线
				float3 binormal = cross(v.normal,v.tangent.xyz)*v.tangent.w;
				//从模型空间到切线空间的转换矩阵
				float3x3 rotation = float3x3(v.tangent.xyz,binormal,v.normal);
				//将光源位置减去顶点位置,这样就得到光照方向了 — 但是我们应该首先将顶点位置乘上光源的w分量,如果是平行光,w分量为0,得到的结果为0,说明顶点位置全变为(0.0, 0.0, 0.0)了,这样光照方向就是源   本的位置   (return objSpaceLightPos.xyz)。对于点光源,w为1,所以乘上顶点位置后,顶点位置无变化,这样计算的光照方向就是(return objSpaceLightPos.xyz – v.xyz)。
				float3 lightDir = mul(unity_WorldToObject,_WorldSpaceLightPos0).xyz - v.vertex*_WorldSpaceLightPos0.w;
				o.lightDir = mul(rotation,lightDir);
				o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
				//o.worldNormal = normalize( mul(v.normal,(float3x3)unity_WorldToObject));
				TRANSFER_SHADOW(o);
                return o;
            }
 
        /*
        将上面的函数拷贝进来
        */

        half4 frag(v2f i) : SV_Target {
                fixed3 burn = tex2D(_BurnMap,i.uvBurnMap).rgb;
                clip(burn.r - _BurnAmount);
                float3 tangentLightDir = normalize(i.lightDir);
                //uppack  normal
				fixed3 tangentNormal;
                fixed4 packedNormal  = tex2D(_BumpMap,i.uvBumpMap);
                #if defined(UNITY_NO_DXT5nm)
				tangentNormal.xyz = packedNormal.xyz*2 -1;
                #else
				// --rgba  -- xyzw 
				//DXTnm 格式中a通道(即w分量)对应发现x分量,g通道(即y分量)对应发现y分量,
				//tangentNormal.xy = packedNormal.ag*2 -1;
				tangentNormal.xy = packedNormal.wy*2 -1;
                //tangentNormal=tangentNormal* _BumpScale;
				tangentNormal.z = sqrt(1.0-max(0,dot(tangentNormal.xy,tangentNormal.xy)));
                #endif

				fixed3 albedo = tex2D(_MainTex,i.uvMainTex).rgb;
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
                fixed3 diffuse = _LightColor0.rgb*albedo*max(0,dot(tangentNormal,tangentLightDir));
                fixed t  = 1 - smoothstep(0.0,_LineWidth,burn.r - _BurnAmount);
                fixed3 burnColor = lerp(_BurnFirstColor,_BurnSecondColor,t);
                burnColor = pow(burnColor,5);
                UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);
                fixed3 finalColor = lerp(ambient+diffuse*atten,burnColor, t* step(0.0001,_BurnAmount));
                return fixed4(finalColor,1);
            }


        ENDCG
        }
    }
    FallBack "Diffuse"
}

效果图:
在这里插入图片描述在这里插入图片描述

<think>好的,用户想学习如何在Unity中制作消融特效。我需要根据提供的引用资料来整理一个教程。首先,引用[1]和[2]提到了使用ShaderShader Graph实现消融特效,而引用[3]则涉及ShaderGraph和粒子系统。我需要结合这些信息,分步骤讲解。 第一步,消融原理。根据引用[1]和[2],消融特效是通过丢弃片元实现的。Shader中使用discard或者alpha测试,Shader Graph可能用Alpha Clip Threshold。需要解释噪声图的作用,比如用噪声纹理控制消融区域。 第二步,使用Shader Graph制作。引用[3]提到用ShaderGraph教程,可能需要创建Unlit Shader Graph,添加噪声纹理,控制消融区域。要详细说明节点连接,比如Sample Texture 2D,Time节点控制消融进度,然后连接到Master节点的Alpha Threshold。 第三步,结合粒子系统。引用[3]还提到灰烬飘散效果,需要粒子系统来表现碎片。这里要说明如何将消融区域与粒子发射位置关联,可能需要脚本控制,根据消融进度发射粒子。 第四步,优化方法。引用[1]和[2]中提到了不同的实现方式,可以对比ShaderShader Graph的区别,比如性能优化或者效果调整。 最后,生成相关问题,比如性能优化、其他特效、粒子系统控制等。确保步骤清晰,用户能逐步跟随操作,同时引用正确的资料。注意用户可能需要代码示例和节点截图,但当前无法提供图片,所以用文字描述节点连接。</think>### Unity消融特效实现教程 消融特效常用于表现物体逐渐化为灰烬或碎片消散的效果。以下是两种主流实现方式: 一、Shader基础实现(基于片元丢弃) 1. 原理:通过噪声纹理控制消融区域 ```csharp Shader "Custom/Dissolve" { Properties { _NoiseTex("Noise Texture", 2D) = "white" {} _Threshold("Threshold", Range(0,1)) = 0 } SubShader { Pass { CGPROGRAM sampler2D _NoiseTex; float _Threshold; fixed4 frag(v2f i) : SV_Target { float noise = tex2D(_NoiseTex, i.uv).r; if(noise < _Threshold) discard; // 关键消融语句 return fixed4(1,1,1,1); } ENDCG } } } ``` 实现步骤: 1. 创建噪声纹理(推荐使用Perlin噪声) 2. 将材质附加到模型 3. 通过脚本控制_Threshold参数动画[^1] 二、Shader Graph可视化实现(基于Alpha测试) 1. 创建Unlit Shader Graph 2. 节点连接: - Sample Texture 2D(噪声图) - Time节点驱动消融进度 - Step节点控制阈值 - 输出到Master节点的Alpha Threshold[^2] 3. 添加边缘发光效果: ```glsl float edge = smoothstep(_Threshold, _Threshold+0.1, noise); emission = edge * _GlowColor; ``` 三、进阶效果实现(灰烬飘散) 1. 粒子系统配置: - 使用Mesh粒子模式 - 发射形状匹配原模型 - 添加湍流力场模拟飘散 2. 脚本控制: ```csharp void Update() { dissolveMaterial.SetFloat("_Threshold", progress); particleSystem.Emit(new Particle() { position = dissolvePoint, velocity = Random.insideUnitSphere * 5f }); } ``` 优化建议: - 使用Mipmap处理噪声纹理 - 对移动端使用低分辨率噪声图 - 开启GPU Instancing提升性能[^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值