200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > shader之——shadowGun代码分析

shader之——shadowGun代码分析

时间:2021-07-06 02:24:39

相关推荐

shader之——shadowGun代码分析

shadowGun是官方一个很早的demo,但是里面的东西真的是值得一学

1.烟火,大多数人都是选择粒子来做这样的烟火,在shadeGun中只是用了一个片

搞定了如此真实的烟火,效率上面真的是比粒子好的不是一般的多。

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader "MADFINGER/Environment/Scroll 2 Layers Sine AlphaBlended" {Properties {_MainTex ("Base layer (RGB)", 2D) = "white" {} //贴图1_DetailTex ("2nd layer (RGB)", 2D) = "white" {} //贴图2_ScrollX ("Base layer Scroll speed X", Float) = 1.0 //贴图1的x方向速度_ScrollY ("Base layer Scroll speed Y", Float) = 0.0 //贴图1的y方向速度_Scroll2X ("2nd layer Scroll speed X", Float) = 1.0 //贴图2的x方向速度_Scroll2Y ("2nd layer Scroll speed Y", Float) = 0.0 //贴图2的y方向速度_SineAmplX ("Base layer sine amplitude X",Float) = 0.5 //贴图1 x方向的扭动幅度_SineAmplY ("Base layer sine amplitude Y",Float) = 0.5 //贴图1 y方向的扭动幅度_SineFreqX ("Base layer sine freq X",Float) = 10 //贴图1 x方向的扭动速度_SineFreqY ("Base layer sine freq Y",Float) = 10 //贴图1 y方向的扭动速度_SineAmplX2 ("2nd layer sine amplitude X",Float) = 0.5 //贴图2 x方向的扭动幅度_SineAmplY2 ("2nd layer sine amplitude Y",Float) = 0.5 //贴图2 y方向的扭动幅度_SineFreqX2 ("2nd layer sine freq X",Float) = 10 //贴图2 x方向的扭动速度_SineFreqY2 ("2nd layer sine freq Y",Float) = 10 //贴图2 y方向的扭动速度_Color("Color", Color) = (1,1,1,1) //主颜色_MMultiplier ("Layer Multiplier", Float) = 2.0 //亮度}SubShader {Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }Blend SrcAlpha OneMinusSrcAlphaCull Off ZWrite OffLOD 100CGINCLUDE#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON#pragma exclude_renderers molehill #include "UnityCG.cginc"sampler2D _MainTex;sampler2D _DetailTex;float4 _MainTex_ST;float4 _DetailTex_ST;float _ScrollX;float _ScrollY;float _Scroll2X;float _Scroll2Y;float _MMultiplier;float _SineAmplX;float _SineAmplY;float _SineFreqX;float _SineFreqY;float _SineAmplX2;float _SineAmplY2;float _SineFreqX2;float _SineFreqY2;float4 _Color;struct v2f {float4 pos : SV_POSITION;float4 uv : TEXCOORD0;fixed4 color : TEXCOORD1;};///核心代码v2f vert (appdata_full v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uv.xy = TRANSFORM_TEX(v.texcoord.xy,_MainTex) + frac(float2(_ScrollX, _ScrollY) * _Time);//贴图1的uv动画 frac(x) 返回标量或矢量的小数o.uv.zw = TRANSFORM_TEX(v.texcoord.xy,_DetailTex) + frac(float2(_Scroll2X, _Scroll2Y) * _Time);//贴图2的uv动画o.uv.x += sin(_Time * _SineFreqX) * _SineAmplX;//每个方向做曲线变化,sin里面的影响变化速度,x在外面的参数影响曲线范围o.uv.y += sin(_Time * _SineFreqY) * _SineAmplY;o.uv.z += sin(_Time * _SineFreqX2) * _SineAmplX2;o.uv.w += sin(_Time * _SineFreqY2) * _SineAmplY2;o.color = _MMultiplier * _Color * v.color; //亮度 * 颜色 * 顶点色return o;}ENDCGPass {CGPROGRAM#pragma vertex vert#pragma fragment frag fixed4 frag (v2f i) : COLOR{fixed4 o;fixed4 tex = tex2D (_MainTex, i.uv.xy);fixed4 tex2 = tex2D (_DetailTex, i.uv.zw);o = tex * tex2 * i.color;return o;}ENDCG } }}

总结,frag函数里很简单,也是他的高效率的原因之一,shader优化的方向,把能在顶点计算的东西都在顶点里面去计算。

2.模拟雾效,淡进淡出效果

GodRays

这里的雾效不是指那种真的全局环境都受影响的大雾,而是一种现象:在视角逐渐接近它的时候,视野逐渐清晰。例如对于体积光,从远处看它可能会感觉很亮,但越接近亮度越小,越能看清后面的物体。这种效果可以很好地让玩家感觉到深度的变化。ShadowGun的解决方法是使用一个简单的网格(Fog planes)+透明纹理来模拟。一旦玩家靠近时,通过减淡颜色+使网格顶点移开(需要移开的原因是因为,即使是完全透明的alpha面也会消耗很多渲染时间,而这里的移开一般是把网格收缩变小,减少透明区域)的方法来模拟这个效果。

而如果要使用这个Shader,就需要在三维软件中处理那么Fog planes:

顶点的透明度用于决定顶点是否可以移动(透明度为0表示不可移动,1为可移动)顶点法线决定移动的方向然后Shader通过计算与观察者的距离来控制雾面的淡入/淡出。

Shader "MADFINGER/Transparent/GodRays" { Properties { _MainTex ("Base texture", 2D) = "white" {} _FadeOutDistNear ("Near fadeout dist", float) = 10 //最近距离 _FadeOutDistFar ("Far fadeout dist", float) = 10000 //最远距离_Multiplier("Multiplier", float) = 1 //亮度_ContractionAmount("Near contraction amount", float) = 5 //顶点移动的速度} SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } Blend One One // Blend One OneMinusSrcColor Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) } LOD 100 CGINCLUDE#include "UnityCG.cginc" sampler2D _MainTex; float _FadeOutDistNear; float _FadeOutDistFar; float _Multiplier; float _ContractionAmount; struct v2f { float4 pos : SV_POSITION; float2 uv: TEXCOORD0; fixed4 color : TEXCOORD1; }; //核心代码v2f vert (appdata_full v) { v2f o; float3 viewPos = mul(UNITY_MATRIX_MV,v.vertex); float dist = length(viewPos); float nfadeout = saturate(dist / _FadeOutDistNear); //如果小于了最近距离,开始渐渐出现,如果大于最近距离,总返回为1float ffadeout = 1 - saturate(max(dist - _FadeOutDistFar,0) * 0.2); //后面的值是 dist <=最远距离时 返回为0,大于后开始返回越接近1,所以用1- //结果就是 dist <=最远距离时 返回1,dist>最远距离时 渐渐为0 0.2是为0的速度//下面就是要把这两个数值结合成一个数值,直接将两个值相乘就可以//值A 值B //1.当dist小于最小距离时候 它也必然小于最大距离 A返回的是0到1的数值 B返回的是1 所以相乘不影响结果//2.当dist大于最小距离 小于最大距离的时候 A 返回的是1 B返回的是1 所以相乘也不影响结果//3.当dist大于最大距离 它必然也大于最小距离A 返回的是1 B返回的是1到0 所以相乘不影响结果ffadeout *= ffadeout; //乘以自身,影响曲线的变化速度nfadeout *= nfadeout; //乘以自身,影响曲线的变化速度nfadeout *= nfadeout; //乘以自身,影响曲线的变化速度nfadeout *= ffadeout; //实现了两个值的相乘,统一成一个数值,也是当作物体的透明度来使用 或者亮度来使用的一个0到1的值float4 vpos = v.vertex; //顶点vpos.xyz -= v.normal * saturate(1 - nfadeout) * v.color.a * _ContractionAmount; //沿顶点法线的反方向缩小模型,结合了顶点色的alpha值,需要动的顶点alpha为1,不需要动的顶点alpha为0 (一般起点不动,其他点向起点进行缩放)结合了强度;//这里用1-nafadeout,因为当alpha值为1的时候,模型不需要缩放,而当alpha值表小的时候 开始缩放,当alpha值为0的时候 模型也缩放为0o.uv = v.texcoord.xy;o.pos = mul(UNITY_MATRIX_MVP, vpos);//顶点裁切(在缩放模型之后)o.color = nfadeout * v.color * _Multiplier; //颜色的亮度 用上面得出的亮度值 x 顶点色的颜色 x 强度return o;}ENDCGPass { CGPROGRAM #pragma vertex vert #pragma fragment frag#pragma fragmentoption ARB_precision_hint_fastest fixed4 frag (v2f i) : COLOR{return tex2D (_MainTex, i.uv.xy) * i.color;} ENDCG } } }

3.闪烁的灯光 这里涉及到比较喜欢的参数 灯光亮暗的时间长度控制

跟上面想比 改了vert部分而已

Blinking GodRays

Shader "MADFINGER/Transparent/Blinking GodRays" {Properties {_MainTex ("Base texture", 2D) = "white" {}_FadeOutDistNear ("Near fadeout dist", float) = 10 //最近距离_FadeOutDistFar ("Far fadeout dist", float) = 10000 //最远距离 _Multiplier("Color multiplier", float) = 1 //颜色亮度_Bias("Bias",float) = 0_TimeOnDuration("ON duration",float) = 0.5 //颜色为亮的时间_TimeOffDuration("OFF duration",float) = 0.5 //颜色为暗的时间_BlinkingTimeOffsScale("Blinking time offset scale (seconds)",float) = 5 //起始时间_SizeGrowStartDist("Size grow start dist",float) = 5 //_SizeGrowEndDist("Size grow end dist",float) = 50_MaxGrowSize("Max grow size",float) = 2.5_NoiseAmount("Noise amount (when zero, pulse wave is used)", Range(0,0.5)) = 0_Color("Color", Color) = (1,1,1,1)}SubShader {Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }Blend One One// Blend One OneMinusSrcColorCull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) }LOD 100CGINCLUDE #include "UnityCG.cginc"sampler2D _MainTex;float _FadeOutDistNear;float _FadeOutDistFar;float _Multiplier;float _Bias;float _TimeOnDuration;float _TimeOffDuration;float _BlinkingTimeOffsScale;float _SizeGrowStartDist;float _SizeGrowEndDist;float _MaxGrowSize;float _NoiseAmount;float4 _Color;struct v2f {float4 pos : SV_POSITION;float2 uv : TEXCOORD0;fixed4 color : TEXCOORD1;};//核心代码v2f vert (appdata_full v){v2f o;float time = _Time.y + _BlinkingTimeOffsScale * v.color.b; float3 viewPos = mul(UNITY_MATRIX_MV,v.vertex);float dist = length(viewPos);float nfadeout = saturate(dist / _FadeOutDistNear);float ffadeout = 1 - saturate(max(dist - _FadeOutDistFar,0) * 0.2);float fracTime = fmod(time,_TimeOnDuration + _TimeOffDuration);//fmod(x,y):返回x/y的余数,如果y为0,结果不可预料float wave = smoothstep(0,_TimeOnDuration * 0.25,fracTime) * (1 - smoothstep(_TimeOnDuration * 0.75,_TimeOnDuration,fracTime));//smoothstep(min,max,x):如果x=min,返回0;如果x=max,返回1;如果x在两者之间,返回0到1之间的数字float noiseTime = time * (6.2831853f / _TimeOnDuration);float noise = sin(noiseTime) * (0.5f * cos(noiseTime * 0.6366f + 56.7272f) + 0.5f);//这个好懵逼 是不是复杂了点 只是改变一下曲线 也是拼 0—1 * ((0-0.5)+0.5) 结果是0到1 的参数float noiseWave = _NoiseAmount * noise + (1 - _NoiseAmount);//noise的程度float distScale = min(max(dist - _SizeGrowStartDist,0) / _SizeGrowEndDist,1); //放大模型的参数wave = _NoiseAmount < 0.01f ? wave : noiseWave;//当这个值小于0.01 就用wave,反之就用noiseWavedistScale = distScale * distScale * _MaxGrowSize * v.color.a;//放大模型的参数wave += _Bias;//wave本为0到1的值,+上这个参数的时候 可以让灯闪的时候不至于全黑 把参数改变成_Bias 到 1+_Bias之间ffadeout *= ffadeout;nfadeout *= nfadeout;nfadeout *= nfadeout;nfadeout *= ffadeout;float4 mdlPos = v.vertex;mdlPos.xyz += distScale * v.normal;//正真的放大模型o.uv = v.texcoord.xy;o.pos = mul(UNITY_MATRIX_MVP, mdlPos);o.color = nfadeout * _Color * _Multiplier * wave;return o;}ENDCGPass {CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma fragmentoption ARB_precision_hint_fastest fixed4 frag (v2f i) : COLOR{ return tex2D (_MainTex, i.uv.xy) * i.color;}ENDCG } }}

亲,如果您觉得本文不错,愿意给我一些动力的话,请用手机扫描二维码即可向我打赏

打赏

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