100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Unity Shader学习:Dissolve消融效果

Unity Shader学习:Dissolve消融效果

时间:2023-06-13 00:39:47

相关推荐

Unity Shader学习:Dissolve消融效果

Unity Shader学习:Dissolve消融效果

消融效果在游戏里非常常用,这里简单的实现下,代码里用到了if分支在shader里可能会费一点,如果想直接用puppet_master大佬版本的话可以自己改一下,主要if分支比较好理解,大佬的写法比较绕但是没用到分支,性能可能更好。

消融效果基本原理:利用噪声图的随机使主贴图在相应的位置逐渐剔除噪声颜色值小于一定阈值的像素,再在更靠内(噪声颜色值比阈值稍大一点)的地方安排一个内边缘,在内外边缘之间显示渐变的消融颜色。

shader部分:

Shader "Custom/DissolveEffect" {Properties {_MainTex("MainTex",2D)="white"{}_NoiseTex("NoiseTex",2D)="white"{}//高光大小_Gloss("Gloss",Range(0.0,20.0)) = 20.0//高光强度_SpecularFactor("SpecularFactor",Range(0.0,5.0)) = 1.0//消融阈值_DissolveThreshold("DissolveThreshold",Range(0.0,1.0)) = 0.5//消融系数(消融边界值=消融系数*消融阈值)_HalfDissolveThresholdFactor("HalfDissolveThresholdFactor",Range(1.0,2.0)) = 1.0//外侧颜色_DissolveEdgeColor("DissolveEdgeColor",Color) = (0,0,0,1)//内侧颜色_DissolveColor("DissolveColor",Color) = (1,0,0,1)}CGINCLUDE#include "Lighting.cginc"#include "UnityCG.cginc"sampler2D _MainTex;sampler2D _NoiseTex;float _Gloss;float _SpecularFactor;float _DissolveThreshold;float _HalfDissolveThresholdFactor;float4 _DissolveEdgeColor;float4 _DissolveColor;struct v2f {float4 pos:SV_POSITION;float3 worldNormal:TEXCOORD0;float2 uv:TEXCOORD1;float3 worldPos:TEXCOORD2;};v2f vert(appdata_full v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uv = v.texcoord;o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;return o;}float4 frag(v2f i) :SV_Target{//直接剔除小于阈值(越黑)的像素float4 noiseTexValue = tex2D(_NoiseTex, i.uv);if (noiseTexValue.r<_DissolveThreshold){discard;}//漫反射float3 worldNormal = normalize(i.worldNormal);float3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);float3 lambert = max(0.0,dot(worldNormal, worldLightDir));float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;float3 diffuseColor = lambert *_LightColor0.xyz+ambient;diffuseColor = diffuseColor * tex2D(_MainTex, i.uv).rgb;//高光float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);float3 halfDir = normalize(worldLightDir + viewDir);float3 specular = _LightColor0.xyz*pow(saturate(dot(halfDir, worldNormal)), _Gloss);float3 finalColor = diffuseColor + specular*_SpecularFactor;//消融边界区域的最小值float halfDissolveThreshold = _DissolveThreshold * _HalfDissolveThresholdFactor;//噪声像素大于消融阈值但小于消融边界值,渐变颜色if (noiseTexValue.r<halfDissolveThreshold){//得到噪声像素在两个边界间的权重float colorFactor = smoothstep(_DissolveThreshold, halfDissolveThreshold, noiseTexValue.r);//根据权重渐变颜色float3 finalColor = lerp(_DissolveColor, _DissolveEdgeColor, colorFactor);return float4(finalColor, 1);}else{//噪声像素大于消融边界值,返回漫反射return float4(finalColor, 1);}/*//用的话需要自行改动部分变量//大佬的优化版本,尽量不在shader中用分支判断的版本,但是代码很难理解啊....float percentage = _DissolveThreshold / dissolveValue.r;//如果当前百分比 - 颜色权重 - 边缘颜色float lerpEdge = sign(percentage - _ColorFactor - halfDissolveThreshold);//貌似sign返回的值还得saturate一下,否则是一个很奇怪的值fixed3 edgeColor = lerp(_DissolveEdgeColor.rgb, _DissolveColor.rgb, saturate(lerpEdge));//最终输出颜色的lerp值float lerpOut = sign(percentage - _ColorFactor);//最终颜色在原颜色和上一步计算的颜色之间差值(其实经过saturate(sign(..))的lerpOut应该只能是0或1)fixed3 colorOut = lerp(color, edgeColor, saturate(lerpOut));return fixed4(colorOut, 1);*/}ENDCGSubShader {Tags{"RenderType"="Opaque"}Pass{CGPROGRAM#pragma vertex vert#pragma fragment fragENDCG}}FallBack "Diffuse"}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。