赞
踩
思路:利用Tessellation Shader(曲面细分着色器)来细化模型的三角面,保证后面生成的毛发足够细,足够密,利用Geometry shader(几何着色器)在细化后的三角面上额外生成向外突出的锥体来模拟毛发,该思路也可以实现其他类似的效果,性能消耗极少。
- Shader "Unlit/Tessellation"
- {
- Properties
- {
- _Color("MainColor",COLOR)=(1,1,1,1)
- _TesseLevel ("Edge length", Range(2,50)) = 20
- _Length("Length", Range(0.01, 10)) = 0.02
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
- Pass
- {
- CGPROGRAM
- #pragma vertex tessvert
- #pragma fragment frag
- #pragma hull hs
- #pragma domain ds
- #pragma geometry geom
- #pragma target 4.0
-
- #include "UnityCG.cginc"
- #include "Lighting.cginc"
- #include "Tessellation.cginc"
- struct Tesse_appdata
- {
- float4 vertex : INTERNALTESSPOS;
- float3 normal : NORMAL;
- };
- struct appdata
- {
- float4 vertex : POSITION;
- float3 normal : NORMAL;
- };
- struct v2f
- {
- float4 vertex : SV_POSITION;
- float3 normal : NORMAL;
- };
-
- fixed4 _Color;
- float _TesseLevel;
- float _Length;
- Tesse_appdata tessvert (appdata v) {
- Tesse_appdata o;
- o.vertex = v.vertex;
- o.normal = v.normal;
- return o;
- }
- v2f vert (appdata v)
- {
- v2f o;
- o.vertex= v.vertex;
- o.normal=v.normal;
- return o;
- }
- float4 tessEdge (float4 v0, float4 v1, float4 v2)
- {
- return UnityEdgeLengthBasedTess (v0, v1, v2, _TesseLevel);//来自Tessellation.cginc
- }
- //========Tessellation Shader部分(细分并平滑三角面)
- UnityTessellationFactors hsconst(InputPatch<Tesse_appdata,3> v) {
- UnityTessellationFactors o;
- float4 tf;
- tf = tessEdge(v[0].vertex, v[1].vertex, v[2].vertex);
- o.edge[0] = tf.x;
- o.edge[1] = tf.y;
- o.edge[2] = tf.z;
- o.inside = tf.w;
- return o;
- }
-
- [UNITY_domain("tri")]
- [UNITY_partitioning("fractional_odd")]
- [UNITY_outputtopology("triangle_cw")]
- [UNITY_patchconstantfunc("hsconst")]
- [UNITY_outputcontrolpoints(3)]
- Tesse_appdata hs (InputPatch<Tesse_appdata,3> v, uint id : SV_OutputControlPointID) {
- return v[id];
- }
-
- [UNITY_domain("tri")]
- v2f ds (UnityTessellationFactors tessFactors, const OutputPatch<Tesse_appdata,3> vi, float3 bary : SV_DomainLocation) {
- appdata v;
- v.vertex = vi[0].vertex*bary.x + vi[1].vertex*bary.y + vi[2].vertex*bary.z;
- //------顶点平滑计算,沿法线方向修正顶点位置
- float3 pp[3];
- pp[0] = v.vertex.xyz - vi[0].normal * (dot(v.vertex.xyz, vi[0].normal) - dot(vi[0].vertex.xyz, vi[0].normal));
- pp[1] = v.vertex.xyz - vi[1].normal * (dot(v.vertex.xyz, vi[1].normal) - dot(vi[1].vertex.xyz, vi[1].normal));
- pp[2] = v.vertex.xyz - vi[2].normal * (dot(v.vertex.xyz, vi[2].normal) - dot(vi[2].vertex.xyz, vi[2].normal));
- v.vertex.xyz = 0.5 * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-0.5) * v.vertex.xyz;
- //------
- v.normal = vi[0].normal*bary.x + vi[1].normal*bary.y + vi[2].normal*bary.z;
- //新的参数=p1的参数*bary.x+p2的参数*bary.y+p3的参数*bary.z;(三点插值算法)
- v2f o = vert(v);
- return o;
- }
- //========
- void ADD_VERT(float3 v,v2f o,inout TriangleStream<v2f> tristream)
- {
- o.vertex = UnityObjectToClipPos(v);
- tristream.Append(o);
- }
- void ADD_TRI(float3 p0,float3 p1,float3 p2,v2f o,inout TriangleStream<v2f> tristream)
- {
- ADD_VERT(p0,o,tristream);
- ADD_VERT(p1,o,tristream);
- ADD_VERT(p2,o,tristream);
- tristream.RestartStrip();
- }
- //======Geometry shader部分(在细分之后的三角面基础上额外生成向外突出的椎体)
- [maxvertexcount(9)]
- void geom(triangle appdata IN[3], inout TriangleStream<v2f> tristream)
- {
- v2f o;
- //--------计算原模型三角面的法线
- float3 edgeA = IN[1].vertex - IN[0].vertex;
- float3 edgeB = IN[2].vertex - IN[0].vertex;
- float3 normalFace = normalize(cross(edgeA, edgeB));
- //-------
- o.normal=-normalFace;
- //根据模型三角面信息额外生成一个向外突出的锥体
- float3 v0 = IN[0].vertex;
- float3 v1 = IN[1].vertex;
- float3 v2 = IN[2].vertex;
- float3 v3 = (IN[0].vertex+IN[1].vertex+IN[2].vertex)/3 + normalFace * _Length;
- ADD_TRI(v0,v1,v2,o,tristream);
- ADD_TRI(v0,v1,v3,o,tristream);
- ADD_TRI(v2,v3,v1,o,tristream);
- }
- //======
- fixed4 frag (v2f i) : SV_Target
- {
- //处理光照等等
- float3 lightDir=normalize(_WorldSpaceLightPos0.xyz);
- float4 diffuseColor=_LightColor0*max(dot(i.normal,lightDir),0);
- return _Color*diffuseColor;
- }
- ENDCG
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。