【Unity】偽線框渲染Shader的實現


線框Shader的渲染在游戲應用上還是有一定的需求,這次分享一個偽的線框渲染Shader。之所以稱之為偽線框,是因為真正的線框應該渲染的是線,這在常規上是使用幾何體着色器輸出線段圖元來實現。但是幾何體着色器是DirectX 10的特性,所以針對移動平台,如果有少量線框渲染需求的,這個實現方法的門檻更低。

先說一下實現的原理:通過模型UV的邊界來實現線框的渲染,也就是要求渲染的每個線段都要位於UV的邊界上。

Mesh操作:

在建模軟件中,將需要線框顯示的邊,作為UV的拆分邊。將UV塊的每條邊放置在UV的四個邊界位置上,因此需要盡量避免三角形的UV。將UV的邊打直,所有UV塊的邊重合並距離UV貼圖的邊界長度一致,來保證渲染線框的粗細一致。三角形的UV,需要插入點使之成為四邊形。為了不影響正常渲染,可以把線框渲染用的UV保存為第二套或第三套UV。

Shader:

  EdgeColor——線框邊的顏色。

  Color——模型覆蓋的顏色。

  Width——線框的寬度(跟UV邊接近UV貼圖邊界的程度有關)。

  需要實現只顯示線框但不現實模型覆蓋色的效果:將Color的Alpha通道設置為0。

代碼如下:

  1 Shader "JaffHan/Wireframe" {
  2 Properties {
  3         _Color("Color",Color)=(1.0,1.0,1.0,1.0)
  4         _EdgeColor("Edge Color",Color)=(1.0,1.0,1.0,1.0)
  5         _Width("Width",Range(0,1))=0.2
  6     }
  7 SubShader {
  8     Tags { 
  9     "Queue"="Transparent" 
 10     "IgnoreProjector"="True" 
 11     "RenderType"="Transparent" 
 12     }
 13     Blend SrcAlpha OneMinusSrcAlpha
 14     LOD 200
 15     Cull Front
 16     zWrite off
 17     Pass {
 18     CGPROGRAM
 19     #pragma vertex vert
 20     #pragma fragment frag
 21     #pragma target 3.0
 22     #include "UnityCG.cginc"
 23 
 24     struct a2v {
 25         half4 uv : TEXCOORD0 ;
 26         half4 vertex : POSITION ;
 27     };
 28 
 29     struct v2f{
 30         half4 pos : SV_POSITION ;
 31         half4 uv : TEXCOORD0  ;            
 32     };
 33     fixed4 _Color;
 34     fixed4 _EdgeColor;
 35     float _Width;
 36     
 37     v2f vert(a2v v)
 38     {
 39         v2f o;
 40         o.uv = v.uv;
 41         o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
 42         return o;
 43     }
 44 
 45 
 46     fixed4 frag(v2f i) : COLOR
 47     {
 48         fixed4 col;
 49         float lx = step(_Width, i.uv.x);
 50         float ly = step(_Width, i.uv.y);
 51         float hx = step(i.uv.x, 1.0 - _Width);
 52         float hy = step(i.uv.y, 1.0 - _Width);
 53         col = lerp(_EdgeColor, _Color, lx*ly*hx*hy);
 54         return col;
 55     }
 56     ENDCG
 57     }
 58     Blend SrcAlpha OneMinusSrcAlpha
 59     LOD 200 
 60     Cull Back
 61     zWrite off
 62     Pass {
 63     CGPROGRAM
 64     #pragma vertex vert
 65     #pragma fragment frag
 66     #pragma target 3.0
 67     #include "UnityCG.cginc"
 68 
 69     struct a2v {
 70         half4 uv : TEXCOORD0 ;
 71         half4 vertex : POSITION ;
 72     };
 73 
 74     struct v2f{
 75         half4 pos : SV_POSITION ;
 76         half4 uv : TEXCOORD0  ;            
 77     };
 78     fixed4 _Color;
 79     fixed4 _EdgeColor;
 80     float _Width;
 81     
 82     v2f vert(a2v v)
 83     {
 84         v2f o;
 85         o.uv = v.uv;
 86         o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
 87         return o;
 88     }
 89 
 90 
 91     fixed4 frag(v2f i) : COLOR
 92     {
 93         fixed4 col;
 94         float lx = step(_Width, i.uv.x);
 95         float ly = step(_Width, i.uv.y);
 96         float hx = step(i.uv.x, 1.0 - _Width);
 97         float hy = step(i.uv.y, 1.0 - _Width);
 98         col = lerp(_EdgeColor, _Color, lx*ly*hx*hy);
 99         return col;
100     }
101     ENDCG
102     }
103 } 
104     FallBack "Diffuse"
105 }
Wireframe

Shader使用來兩個Pass渲染,來避免產生透明混合出現的深度問題。第一個Pass渲染背面,第二個Pass渲染正面。

step是一個比較大小的操作,實現如下:

step step(a, x) Returns (x >= a) ? 1 : 0

lx/ly/hx/hy用於判斷渲染像素是否位於中心和UV中心一致,變長為1-_Width*2的正方形內,如果不在,即為線條。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM