当前位置:   article > 正文

Unity Tessellation Shader+Geometry shader实现毛发效果_曲面细分shader后加geometry shader

曲面细分shader后加geometry shader

思路:利用Tessellation Shader(曲面细分着色器)来细化模型的三角面,保证后面生成的毛发足够细,足够密,利用Geometry shader(几何着色器)在细化后的三角面上额外生成向外突出的锥体来模拟毛发,该思路也可以实现其他类似的效果,性能消耗极少。

  1. Shader "Unlit/Tessellation"
  2. {
  3. Properties
  4. {
  5. _Color("MainColor",COLOR)=(1,1,1,1)
  6. _TesseLevel ("Edge length", Range(2,50)) = 20
  7. _Length("Length", Range(0.01, 10)) = 0.02
  8. }
  9. SubShader
  10. {
  11. Tags { "RenderType"="Opaque" }
  12. LOD 100
  13. Pass
  14. {
  15. CGPROGRAM
  16. #pragma vertex tessvert
  17. #pragma fragment frag
  18. #pragma hull hs
  19. #pragma domain ds
  20. #pragma geometry geom
  21. #pragma target 4.0
  22. #include "UnityCG.cginc"
  23. #include "Lighting.cginc"
  24. #include "Tessellation.cginc"
  25. struct Tesse_appdata
  26. {
  27. float4 vertex : INTERNALTESSPOS;
  28. float3 normal : NORMAL;
  29. };
  30. struct appdata
  31. {
  32. float4 vertex : POSITION;
  33. float3 normal : NORMAL;
  34. };
  35. struct v2f
  36. {
  37. float4 vertex : SV_POSITION;
  38. float3 normal : NORMAL;
  39. };
  40. fixed4 _Color;
  41. float _TesseLevel;
  42. float _Length;
  43. Tesse_appdata tessvert (appdata v) {
  44. Tesse_appdata o;
  45. o.vertex = v.vertex;
  46. o.normal = v.normal;
  47. return o;
  48. }
  49. v2f vert (appdata v)
  50. {
  51. v2f o;
  52. o.vertex= v.vertex;
  53. o.normal=v.normal;
  54. return o;
  55. }
  56. float4 tessEdge (float4 v0, float4 v1, float4 v2)
  57. {
  58. return UnityEdgeLengthBasedTess (v0, v1, v2, _TesseLevel);//来自Tessellation.cginc
  59. }
  60. //========Tessellation Shader部分(细分并平滑三角面)
  61. UnityTessellationFactors hsconst(InputPatch<Tesse_appdata,3> v) {
  62. UnityTessellationFactors o;
  63. float4 tf;
  64. tf = tessEdge(v[0].vertex, v[1].vertex, v[2].vertex);
  65. o.edge[0] = tf.x;
  66. o.edge[1] = tf.y;
  67. o.edge[2] = tf.z;
  68. o.inside = tf.w;
  69. return o;
  70. }
  71. [UNITY_domain("tri")]
  72. [UNITY_partitioning("fractional_odd")]
  73. [UNITY_outputtopology("triangle_cw")]
  74. [UNITY_patchconstantfunc("hsconst")]
  75. [UNITY_outputcontrolpoints(3)]
  76. Tesse_appdata hs (InputPatch<Tesse_appdata,3> v, uint id : SV_OutputControlPointID) {
  77. return v[id];
  78. }
  79. [UNITY_domain("tri")]
  80. v2f ds (UnityTessellationFactors tessFactors, const OutputPatch<Tesse_appdata,3> vi, float3 bary : SV_DomainLocation) {
  81. appdata v;
  82. v.vertex = vi[0].vertex*bary.x + vi[1].vertex*bary.y + vi[2].vertex*bary.z;
  83. //------顶点平滑计算,沿法线方向修正顶点位置
  84. float3 pp[3];
  85. pp[0] = v.vertex.xyz - vi[0].normal * (dot(v.vertex.xyz, vi[0].normal) - dot(vi[0].vertex.xyz, vi[0].normal));
  86. pp[1] = v.vertex.xyz - vi[1].normal * (dot(v.vertex.xyz, vi[1].normal) - dot(vi[1].vertex.xyz, vi[1].normal));
  87. pp[2] = v.vertex.xyz - vi[2].normal * (dot(v.vertex.xyz, vi[2].normal) - dot(vi[2].vertex.xyz, vi[2].normal));
  88. v.vertex.xyz = 0.5 * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-0.5) * v.vertex.xyz;
  89. //------
  90. v.normal = vi[0].normal*bary.x + vi[1].normal*bary.y + vi[2].normal*bary.z;
  91. //新的参数=p1的参数*bary.x+p2的参数*bary.y+p3的参数*bary.z;(三点插值算法)
  92. v2f o = vert(v);
  93. return o;
  94. }
  95. //========
  96. void ADD_VERT(float3 v,v2f o,inout TriangleStream<v2f> tristream)
  97. {
  98. o.vertex = UnityObjectToClipPos(v);
  99. tristream.Append(o);
  100. }
  101. void ADD_TRI(float3 p0,float3 p1,float3 p2,v2f o,inout TriangleStream<v2f> tristream)
  102. {
  103. ADD_VERT(p0,o,tristream);
  104. ADD_VERT(p1,o,tristream);
  105. ADD_VERT(p2,o,tristream);
  106. tristream.RestartStrip();
  107. }
  108. //======Geometry shader部分(在细分之后的三角面基础上额外生成向外突出的椎体)
  109. [maxvertexcount(9)]
  110. void geom(triangle appdata IN[3], inout TriangleStream<v2f> tristream)
  111. {
  112. v2f o;
  113. //--------计算原模型三角面的法线
  114. float3 edgeA = IN[1].vertex - IN[0].vertex;
  115. float3 edgeB = IN[2].vertex - IN[0].vertex;
  116. float3 normalFace = normalize(cross(edgeA, edgeB));
  117. //-------
  118. o.normal=-normalFace;
  119. //根据模型三角面信息额外生成一个向外突出的锥体
  120. float3 v0 = IN[0].vertex;
  121. float3 v1 = IN[1].vertex;
  122. float3 v2 = IN[2].vertex;
  123. float3 v3 = (IN[0].vertex+IN[1].vertex+IN[2].vertex)/3 + normalFace * _Length;
  124. ADD_TRI(v0,v1,v2,o,tristream);
  125. ADD_TRI(v0,v1,v3,o,tristream);
  126. ADD_TRI(v2,v3,v1,o,tristream);
  127. }
  128. //======
  129. fixed4 frag (v2f i) : SV_Target
  130. {
  131. //处理光照等等
  132. float3 lightDir=normalize(_WorldSpaceLightPos0.xyz);
  133. float4 diffuseColor=_LightColor0*max(dot(i.normal,lightDir),0);
  134. return _Color*diffuseColor;
  135. }
  136. ENDCG
  137. }
  138. }
  139. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/233308
推荐阅读
相关标签
  

闽ICP备14008679号