Unity3D教程:使用Shader实现雪花飘飞效果

发表于2017-01-17
评论0 2.6k浏览
  Unity3D 如何实现雪花飘飞的效果呢,这就需要用到Shader,方法其实非常的简单,不会的就一起来看看这个用Unity3D 实现雪花飘飞效果的代码吧。
  
  1.新建一个unity3d 项目,新建一个CameraFilterPack_Atmosphere_Snow_8bits.shader文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
Shader "CameraFilterPack/Atmosphere_Snow_8bits" {
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_TimeX ("Time", Range(0.0, 1.0)) = 1.0
_ScreenResolution ("_ScreenResolution", Vector) = (0.,0.,0.,0.)
}
SubShader
{
Pass
{
ZTest Always
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma target 3.0
#pragma glsl
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
uniform float _TimeX;
uniform float _Value;
uniform float _Value2;
uniform float4 _ScreenResolution;
uniform float2 _MainTex_TexelSize;
struct appdata_t
{
float4 vertex   : POSITION;
float4 color    : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
half2 texcoord  : TEXCOORD0;
float4 vertex   : SV_POSITION;
fixed4 color    : COLOR;
};
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color;
return OUT;
}
 
inline float2 mod(float2 x,float2 modu) {
  return x - floor(x * (1.0 / modu)) * modu;
}
 
 
inline float rand(float2 co)
{
float r;
co = floor(co*_Value2);
  r = frac(sin(dot(co.xy,float2(12.9898,78.233))) * 43758.5453);
   return r;
}
 
float4 frag (v2f i) : COLOR
{
float2 uv = i.texcoord.xy;
 
    float3 col=tex2D(_MainTex,uv).rgb;
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
uv.y = 1-uv.y;
#endif
   float ts=uv.y-.2+sin(uv.x*4.0+7.4*cos(uv.x*10.0))*0.005;
  
    uv*=2.0;
     
    float c=cos(8*0.01),si=sin(8*0.01);
uv=(uv-0.5)*float2(c+si,-si+c);
     
    float s=rand(mod(uv * 1.01 +float2(_TimeX,_TimeX)*float2(0.02,0.501),1.0)).r;
    col=lerp(col,float3(1.0,1.0,1.0),smoothstep(0.9,1.0, s * .9 * _Value));
     
  s=rand(mod(uv * 1.07 +float2(_TimeX,_TimeX)*float2(0.02,0.501),1.0)).r;
  col=lerp(col,float3(1.0,1.0,1.0),smoothstep(0.9,1.0, s * 1. * _Value));
     
s=rand(mod(uv+float2(_TimeX,_TimeX)*float2(0.05,0.5),1.0)).r;
    col=lerp(col,float3(1.0,1.0,1.0),smoothstep(0.9,1.0, s * .98 * _Value));
 
s=rand(mod(uv * .9 +float2(_TimeX,_TimeX)*float2(0.02,0.51),1.0)).r;
    col=lerp(col,float3(1.0,1.0,1.0),smoothstep(0.9,1.0, s * .99 * _Value));
 
s=rand(mod(uv * .75 +float2(_TimeX,_TimeX)*float2(0.07,0.493),1.0)).r;
    col=lerp(col,float3(1.0,1.0,1.0),smoothstep(0.9,1.0, s * 1. * _Value));
 
s=rand(mod(uv * .5 +float2(_TimeX,_TimeX)*float2(0.03,0.504),1.0)).r;
    col=lerp(col,float3(1.0,1.0,1.0),smoothstep(0.94,1.0, s * 1. * _Value));
 
s=rand(mod(uv * .3 +float2(_TimeX,_TimeX)*float2(0.02,0.497),1.0)).r;
    col=lerp(col,float3(1.0,1.0,1.0),smoothstep(0.95,1.0, s * 1. * _Value));
 
s=rand(mod(uv * .1 +float2(_TimeX,_TimeX)*float2(0.0,0.51),1.0)).r;
col=lerp(col,float3(1.0,1.0,1.0),smoothstep(0.96,1.0, s * 1. * _Value));
 
s=rand(mod(uv * .03 +float2(_TimeX,_TimeX)*float2(0.0,0.523),1.0)).r;
col=lerp(col,float3(1.0,1.0,1.0),smoothstep(0.99,1.0, s * 1. * _Value));
     
return  float4(col,1.0);
}
ENDCG
}
}
}
  
  2.为了方便更改shader的一些参数,所以我们新建一个CameraFilterPack_Atmosphere_Snow_8bits.cs 组件类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
[AddComponentMenu ("Camera Filter Pack/Pixel/Snow_8bits")]
public class CameraFilterPack_Atmosphere_Snow_8bits : MonoBehaviour {
#region Variables
public Shader SCShader;
private float TimeX = 1.0f;
private Vector4 ScreenResolution;
private Material SCMaterial;
[Range(0.9f, 2f)]
public float Threshold = 1f;
[Range(8f, 256f)]
public float Size = 64f;
[Range(0f, 10f)]
private float Value3 = 1f;
[Range(0f, 10f)]
private float Value4 = 1f;
public static float ChangeValue;
public static float ChangeValue2;
public static float ChangeValue3;
public static float ChangeValue4;
#endregion
#region Properties
Material material
{
get
{
if(SCMaterial == null)
{
SCMaterial = new Material(SCShader);
SCMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return SCMaterial;
}
}
#endregion
void Start ()
{
ChangeValue = Threshold;
ChangeValue2 = Size;
ChangeValue3 = Value3;
ChangeValue4 = Value4;
SCShader = Shader.Find("CameraFilterPack/Atmosphere_Snow_8bits");
if(!SystemInfo.supportsImageEffects)
{
enabled = false;
return;
}
}
 
void OnRenderImage (RenderTexture sourceTexture, RenderTexture destTexture)
{
if(SCShader != null)
{
TimeX+=Time.deltaTime;
if (TimeX>100)  TimeX=0;
material.SetFloat("_TimeX", TimeX);
material.SetFloat("_Value", Threshold);
material.SetFloat("_Value2", Size);
material.SetFloat("_Value3", Value3);
material.SetFloat("_Value4", Value4);
material.SetVector("_ScreenResolution",new Vector4(sourceTexture.width,sourceTexture.height,0.0f,0.0f));
Graphics.Blit(sourceTexture, destTexture, material);
}
else
{
Graphics.Blit(sourceTexture, destTexture);
}
}
void OnValidate()
{
ChangeValue=Threshold;
ChangeValue2=Size;
ChangeValue3=Value3;
ChangeValue4=Value4;
}
void Update ()
{
if (Application.isPlaying)
{
Threshold = ChangeValue;
Size = ChangeValue2;
Value3 = ChangeValue3;
Value4 = ChangeValue4;
}
#if UNITY_EDITOR
if (Application.isPlaying!=true)
{
SCShader = Shader.Find("CameraFilterPack/Atmosphere_Snow_8bits");
}
#endif
}
void OnDisable ()
{
if(SCMaterial)
{
DestroyImmediate(SCMaterial);
}
}
}
  
  3.在摄像机上附加AddCameraFilter.cs组件,为了方便控制看出效果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using UnityEngine;
 
public class AddCameraFilter : MonoBehaviour {
 
    private CameraFilterPack_Atmosphere_Snow_8bits _cameraFilterPack;
    // Use this for initialization
    void Start()
    {
        _cameraFilterPack = GetComponent();
    }
 
    // Update is called once per frame
    void OnGUI()
    {
 
        if (GUI.Button(new Rect(50, 200, 200, 30), "添加雪花效果"))
        {
            if (_cameraFilterPack == null)
                _cameraFilterPack = gameObject.AddComponent();
            if (_cameraFilterPack != null)
                _cameraFilterPack.enabled = true;
        }
        if (GUI.Button(new Rect(50, 250, 200, 30), "移除雪花效果"))
        {
            if (_cameraFilterPack != null)
                _cameraFilterPack.enabled = false;
        }
    }
}
  
  4.最后我们直接运行项目看效果。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引