SHOW:
|
|
- or go back to the newest paste.
1 | #if defined(SHADER_API_D3D11) || defined(SHADER_API_GLES3) || defined(SHADER_API_GLCORE) || defined(SHADER_API_VULKAN) || defined(SHADER_API_METAL) || defined(SHADER_API_PSSL) | |
2 | #define UNITY_CAN_COMPILE_TESSELLATION 1 | |
3 | # define UNITY_domain domain | |
4 | # define UNITY_partitioning partitioning | |
5 | # define UNITY_outputtopology outputtopology | |
6 | # define UNITY_patchconstantfunc patchconstantfunc | |
7 | # define UNITY_outputcontrolpoints outputcontrolpoints | |
8 | #endif | |
9 | ||
10 | ||
11 | ||
12 | // The structure definition defines which variables it contains. | |
13 | // This example uses the Attributes structure as an input structure in | |
14 | // the vertex shader. | |
15 | ||
16 | // vertex to fragment struct | |
17 | struct Varyings | |
18 | { | |
19 | float4 color : COLOR; | |
20 | float3 normal : NORMAL; | |
21 | float4 vertex : SV_POSITION; | |
22 | float2 uv : TEXCOORD0; | |
23 | float4 noise : TEXCOORD1; | |
24 | }; | |
25 | ||
26 | ||
27 | // tessellation data | |
28 | struct TessellationFactors | |
29 | { | |
30 | float edge[3] : SV_TessFactor; | |
31 | float inside : SV_InsideTessFactor; | |
32 | }; | |
33 | ||
34 | // Extra vertex struct | |
35 | struct ControlPoint | |
36 | { | |
37 | float4 vertex : INTERNALTESSPOS; | |
38 | float2 uv : TEXCOORD0; | |
39 | float4 color : COLOR; | |
40 | float3 normal : NORMAL; | |
41 | }; | |
42 | ||
43 | // the original vertex struct | |
44 | struct Attributes | |
45 | { | |
46 | float4 vertex : POSITION; | |
47 | float3 normal : NORMAL; | |
48 | float2 uv : TEXCOORD0; | |
49 | float4 color : COLOR; | |
50 | ||
51 | }; | |
52 | ||
53 | // tessellation variables, add these to your shader properties | |
54 | float _Tess; | |
55 | float _MaxTessDistance; | |
56 | ||
57 | // info so the GPU knows what to do (triangles) and how to set it up , clockwise, fractional division | |
58 | // hull takes the original vertices and outputs more | |
59 | [UNITY_domain("tri")] | |
60 | [UNITY_outputcontrolpoints(3)] | |
61 | [UNITY_outputtopology("triangle_cw")] | |
62 | [UNITY_partitioning("fractional_odd")] | |
63 | //[UNITY_partitioning("fractional_even")] | |
64 | //[UNITY_partitioning("pow2")] | |
65 | //[UNITY_partitioning("integer")] | |
66 | [UNITY_patchconstantfunc("patchConstantFunction")] | |
67 | ControlPoint hull(InputPatch<ControlPoint, 3> patch, uint id : SV_OutputControlPointID) | |
68 | { | |
69 | return patch[id]; | |
70 | } | |
71 | ||
72 | TessellationFactors UnityCalcTriEdgeTessFactors (float3 triVertexFactors) | |
73 | { | |
74 | TessellationFactors tess; | |
75 | tess.edge[0] = 0.5 * (triVertexFactors.y + triVertexFactors.z); | |
76 | tess.edge[1] = 0.5 * (triVertexFactors.x + triVertexFactors.z); | |
77 | tess.edge[2] = 0.5 * (triVertexFactors.x + triVertexFactors.y); | |
78 | tess.inside = (triVertexFactors.x + triVertexFactors.y + triVertexFactors.z) / 3.0f; | |
79 | return tess; | |
80 | } | |
81 | ||
82 | // fade tessellation at a distance | |
83 | float CalcDistanceTessFactor(float4 vertex, float minDist, float maxDist, float tess) | |
84 | { | |
85 | float3 worldPosition = mul(unity_ObjectToWorld, vertex).xyz; | |
86 | float dist = distance(worldPosition, _WorldSpaceCameraPos); | |
87 | float f = clamp(1.0 - (dist - minDist) / (maxDist - minDist), 0.01, 1.0); | |
88 | ||
89 | return f * tess; | |
90 | } | |
91 | ||
92 | TessellationFactors DistanceBasedTess(float4 v0, float4 v1, float4 v2, float minDist, float maxDist, float tess) | |
93 | { | |
94 | float3 f; | |
95 | f.x = CalcDistanceTessFactor(v0, minDist, maxDist, tess); | |
96 | f.y = CalcDistanceTessFactor(v1, minDist, maxDist, tess); | |
97 | f.z = CalcDistanceTessFactor(v2, minDist, maxDist, tess); | |
98 | ||
99 | return UnityCalcTriEdgeTessFactors(f); | |
100 | } | |
101 | ||
102 | ||
103 | ||
104 | float UnityCalcEdgeTessFactor (float3 wpos0, float3 wpos1, float edgeLen) | |
105 | { | |
106 | // distance to edge center | |
107 | float dist = distance (0.5 * (wpos0+wpos1), _WorldSpaceCameraPos); | |
108 | // length of the edge | |
109 | float len = distance(wpos0, wpos1); | |
110 | // edgeLen is approximate desired size in pixels | |
111 | float f = max(len * _ScreenParams.y / (edgeLen * dist), 1.0); | |
112 | return f; | |
113 | } | |
114 | ||
115 | ||
116 | float UnityDistanceFromPlane (float3 pos, float4 plane) | |
117 | { | |
118 | float d = dot (float4(pos,1.0f), plane); | |
119 | return d; | |
120 | } | |
121 | ||
122 | ||
123 | // Returns true if triangle with given 3 world positions is outside of camera's view frustum. | |
124 | // cullEps is distance outside of frustum that is still considered to be inside (i.e. max displacement) | |
125 | bool UnityWorldViewFrustumCull (float3 wpos0, float3 wpos1, float3 wpos2, float cullEps) | |
126 | { | |
127 | float4 planeTest; | |
128 | ||
129 | // left | |
130 | planeTest.x = (( UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[0]) > -cullEps) ? 1.0f : 0.0f ) + | |
131 | (( UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[0]) > -cullEps) ? 1.0f : 0.0f ) + | |
132 | (( UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[0]) > -cullEps) ? 1.0f : 0.0f ); | |
133 | // right | |
134 | planeTest.y = (( UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[1]) > -cullEps) ? 1.0f : 0.0f ) + | |
135 | (( UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[1]) > -cullEps) ? 1.0f : 0.0f ) + | |
136 | (( UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[1]) > -cullEps) ? 1.0f : 0.0f ); | |
137 | // top | |
138 | planeTest.z = (( UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[2]) > -cullEps) ? 1.0f : 0.0f ) + | |
139 | (( UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[2]) > -cullEps) ? 1.0f : 0.0f ) + | |
140 | (( UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[2]) > -cullEps) ? 1.0f : 0.0f ); | |
141 | // bottom | |
142 | planeTest.w = (( UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[3]) > -cullEps) ? 1.0f : 0.0f ) + | |
143 | (( UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[3]) > -cullEps) ? 1.0f : 0.0f ) + | |
144 | (( UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[3]) > -cullEps) ? 1.0f : 0.0f ); | |
145 | ||
146 | // has to pass all 4 plane tests to be visible | |
147 | return !all (planeTest); | |
148 | } | |
149 | ||
150 | ||
151 | // Desired edge length based tessellation: | |
152 | // Approximate resulting edge length in pixels is "edgeLength". | |
153 | // Does not take viewing FOV into account, just flat out divides factor by distance. | |
154 | TessellationFactors UnityEdgeLengthBasedTess (float4 v0, float4 v1, float4 v2, float edgeLength) | |
155 | { | |
156 | float3 pos0 = mul(unity_ObjectToWorld,v0).xyz; | |
157 | float3 pos1 = mul(unity_ObjectToWorld,v1).xyz; | |
158 | float3 pos2 = mul(unity_ObjectToWorld,v2).xyz; | |
159 | TessellationFactors tess; | |
160 | tess.edge[0] = UnityCalcEdgeTessFactor (pos1, pos2, edgeLength); | |
161 | tess.edge[1] = UnityCalcEdgeTessFactor (pos2, pos0, edgeLength); | |
162 | tess.edge[2] = UnityCalcEdgeTessFactor (pos0, pos1, edgeLength); | |
163 | tess.inside = (tess.edge[0] + tess.edge[1] + tess.edge[2]) / 3.0f; | |
164 | return tess; | |
165 | } | |
166 | ||
167 | ||
168 | // Same as UnityEdgeLengthBasedTess, but also does patch frustum culling: | |
169 | // patches outside of camera's view are culled before GPU tessellation. Saves some wasted work. | |
170 | TessellationFactors UnityEdgeLengthBasedTessCull (float4 v0, float4 v1, float4 v2, float edgeLength, float maxDisplacement) | |
171 | { | |
172 | float3 pos0 = mul(unity_ObjectToWorld,v0).xyz; | |
173 | float3 pos1 = mul(unity_ObjectToWorld,v1).xyz; | |
174 | float3 pos2 = mul(unity_ObjectToWorld,v2).xyz; | |
175 | TessellationFactors tess; | |
176 | ||
177 | if (UnityWorldViewFrustumCull(pos0, pos1, pos2, maxDisplacement)) | |
178 | { | |
179 | tess.edge[0] = 0.0f; | |
180 | tess.edge[1] = 0.0f; | |
181 | tess.edge[2] = 0.0f; | |
182 | tess.inside = 0.0f; | |
183 | } | |
184 | else | |
185 | { | |
186 | tess.edge[0] = UnityCalcEdgeTessFactor (pos1, pos2, edgeLength); | |
187 | tess.edge[1] = UnityCalcEdgeTessFactor (pos2, pos0, edgeLength); | |
188 | tess.edge[2] = UnityCalcEdgeTessFactor (pos0, pos1, edgeLength); | |
189 | tess.inside = (tess.edge[0] + tess.edge[1] + tess.edge[2]) / 3.0f; | |
190 | } | |
191 | return tess; | |
192 | } | |
193 | ||
194 | TessellationFactors patchConstantFunction(InputPatch<ControlPoint, 3> patch) | |
195 | { | |
196 | float minDist = 2.0; | |
197 | float maxDist = _MaxTessDistance + minDist; | |
198 | TessellationFactors f; | |
199 | ||
200 | // distance based tesselation | |
201 | return DistanceBasedTess(patch[0].vertex, patch[1].vertex, patch[2].vertex, minDist, maxDist, _Tess); | |
202 | ||
203 | // continious tesselation based on _Tess being the edge length | |
204 | // return UnityEdgeLengthBasedTess(patch[0].vertex, patch[1].vertex, patch[2].vertex, _Tess); | |
205 | // continious tesselation based on _Tess being the edge length, with camrea culling | |
206 | // return UnityEdgeLengthBasedTessCull(patch[0].vertex, patch[1].vertex, patch[2].vertex, _Tess, _MaxTessDistance); | |
207 | ||
208 | } | |
209 | ||
210 | #define Interpolate(fieldName) v.fieldName = \ | |
211 | patch[0].fieldName * barycentricCoordinates.x + \ | |
212 | patch[1].fieldName * barycentricCoordinates.y + \ | |
213 | patch[2].fieldName * barycentricCoordinates.z; | |
214 | ||
215 | ||
216 | ||
217 | // second vertex, copy to shader | |
218 | //Varyings vert(Attributes input) | |
219 | //{ | |
220 | // Varyings output; | |
221 | // // put your vertex manipulation here , ie: input.vertex.xyz += distortiontexture | |
222 | // output.vertex = TransformObjectToHClip(input.vertex.xyz); | |
223 | // output.color = input.color; | |
224 | // output.normal = input.normal; | |
225 | // output.uv = input.uv; | |
226 | // return output; | |
227 | //} | |
228 | ||
229 | ||
230 | ||
231 | // domain, copy to shader | |
232 | //[UNITY_domain("tri")] | |
233 | //Varyings domain(TessellationFactors factors, OutputPatch<ControlPoint, 3> patch, float3 barycentricCoordinates : SV_DomainLocation) | |
234 | //{ | |
235 | // Attributes v; | |
236 | // | |
237 | // | |
238 | // Interpolate(vertex) | |
239 | // Interpolate(uv) | |
240 | // Interpolate(color) | |
241 | // Interpolate(normal) | |
242 | // | |
243 | // return vert(v); | |
244 | //} | |
245 |