先上效果图:
静态对比图:
简单实现思路,从两点出发,一个是去掉绚丽的颜色(变灰处理咯),一个是贴上大理石纹理(看起来更像石头点)。
float grey = dot(col.rgb, float3(0.299, 0.587, 0.114));
col.rgb = lerp(col.rgb, float3(grey, grey, grey), _StatueDegree);
纹理采样的RGB值Dot灰度系数即可,下面的_StatueDegree系数是石化程度,为了达到一个渐变的效果,所以采用插值计算lerp.
为了让单位石化后看起来更像石头,所以可以考虑添加一点大理石的纹路混合在上面,就简单在网上截一张大理石纹理,比如这样的:
通过纹理采样的方式将采样结果乘上原来的颜色:
fixed4 colStatue = tex2D(_StatueTex, i.uv2);
col.rgb *= lerp(fixed3(1,1,1), colStatue.rgb, _StatueDegree) * lerp(1,_Brightness, _StatueDegree);
这里有两个lerp操作,第一个则是通过石化程度的变量来控制大理石纹理颜色值所占的比重,当然乘上的结果肯定是没有乘1的值大,也就是说乘上大理石纹理颜色后,整体的颜色值整体会变的更小,表现上模型会变暗,所以需要在通过一个_Brightness(亮度)参数来调节整体的亮度,使得石化后不会变暗。
//Created by Vitens
//石化效果
Shader "Vitens/Petrifaction"
{
Properties{
_MainTex("Main Tex", 2D) = "white" {}
_StatueTex("Statue Tex", 2D) = "white" {}
_StatueDegree("石化程度", range(0, 1)) = 0.5
_Brightness("亮度", range(0.5, 3)) = 1
_Tint("Tint", color) = (1,1,1,1)
}
SubShader
{
Pass
{
Tags { "LightMode" = "ForwardBase" }
blend srcAlpha oneMinussrcalpha
Cull off
ZWrite on
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _StatueTex;
float4 _StatueTex_ST;
fixed4 _Tint;
float _StatueDegree;
float _Brightness;
struct a2v {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
float2 uv2 : TEXCOORD1;
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.uv2 = TRANSFORM_TEX(v.texcoord, _StatueTex);
return o;
}
float4 frag(v2f i) : SV_Target {
fixed4 col = tex2D(_MainTex, i.uv);
fixed4 colStatue = tex2D(_StatueTex, i.uv2);
float grey = dot(col.rgb, float3(0.299, 0.587, 0.114));
col.rgb = lerp(col.rgb, float3(grey, grey, grey), _StatueDegree);
col.rgb *= lerp(fixed3(1,1,1), colStatue.rgb, _StatueDegree) * lerp(1,_Brightness, _StatueDegree);
return col * _Tint;
}
ENDCG
}
}
FallBack "Diffuse"
}
bingo.