Advertisement
annapuppet

CustomTessellation.hlsl

Jul 8th, 2022
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement