zoukankan      html  css  js  c++  java
  • 【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的正方形内,如果不在,即为线条。

  • 相关阅读:
    rsync用法详细解释
    配置本地yum仓库
    电脑硬件知识
    LVM逻辑卷管理
    前端文本截断
    程序员编写技术文档的新手指南
    JavaScript 是世界上最好的语言?
    一天只工作 3 小时的程序员,已坚持两年
    数据库水平切分方法
    MySQL 笔记整理(1) --基础架构,一条SQL查询语句如何执行
  • 原文地址:https://www.cnblogs.com/jaffhan/p/7389444.html
Copyright © 2011-2022 走看看