参考文章。
1.知识要点
- geometry shader
基于 shader model 4.0的Geometry shader.
Vertex -> Geometry -> Fragment
#pragma geometry:dx10及以上,可以使用。#pragma target 4.0会自动开启。 - Shader Model 4.0
DX10中加入的新特性,引入Geometry shader,可以操纵图元。
2.修改实例:模型沙粒化掉落效果
1.确保Unity PlayerSetting -> Graphics APIs (for Windows)选择的了Direct3D10以上,并且在第一个。
2.效果如下:
3.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
106Shader "YanCheZuo/geomSandShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Speed("Speed", Float) = -3
_AccelerationValue("AccelerationValue", Float) = 10
_FloorY("Floor Y",Float) = -0.5
_ExploSpeed("ExploSpeed",Float) = 0.4 // 风化速度
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2g
{
float2 uv : TEXCOORD0;
float4 vertex : POSITION;
};
struct g2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float _Speed;
float _AccelerationValue;
float _StartTime;
float _FloorY;
float _ExploSpeed;
v2g vert (appdata v)
{
v2g o;
o.vertex = v.vertex;
o.uv = v.uv;
return o;
}
[maxvertexcount(1)]
void geom(triangle v2g IN[3], inout PointStream<g2f> pointStream)
{
g2f o;
float3 v1 = IN[1].vertex - IN[0].vertex;
float3 v2 = IN[2].vertex - IN[0].vertex;
float3 norm = normalize(cross(v1, v2));
float3 tempPos = (IN[0].vertex + IN[1].vertex + IN[2].vertex) / 3;
float realTime = _Time.y - _StartTime;
// 修改
float3 worldPos = mul(unity_ObjectToWorld, tempPos).xyz; // 获取顶点的世界坐标
worldPos.y -= _Speed * realTime + .5 * _AccelerationValue * pow(realTime, 2);
if(_FloorY<worldPos.y)
{
tempPos -= norm * (_ExploSpeed * realTime);
worldPos = mul(unity_ObjectToWorld, tempPos).xyz; // 再算一次顶点的世界坐标
worldPos.y -= _Speed * realTime + .5 * _AccelerationValue * pow(realTime, 2);
}
else
{
worldPos.y = max(_FloorY, worldPos.y);
}
tempPos = mul(unity_WorldToObject, worldPos).xyz;
o.vertex = UnityObjectToClipPos(tempPos);
o.uv = (IN[0].uv + IN[1].uv + IN[2].uv) / 3;
pointStream.Append(o);
}
fixed4 frag (g2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}