最终效果:

参考了一个免费插件

基础思路======================================
在几何阶段计算每个顶点到第三边的距离,在片元中就可以插值得到每个点到顶点的距离
根据最小的距离只计算是否需要显示,结果就是只绘制边线

基础知识======================================
Geometry 在 Vertex 和 Fragment 之间 可选步骤
根据Vertex传入的顶点参数做一些调整,生成改动后的顶点结构,再调用Fragment着色器

//声明使用的几何着色器函数,类似声明 vertex 和 fragment
#pragma geometry geom

//限制GS输出的最大顶点数
[maxvertexcount(3)]
//第一个时入参  第二个是调整以后的数据
void geom(triangle v2g p[3], inout TriangleStream<g2f> triStream)
{
    UCLAGL_geom( p, triStream);
}

入参格式 像fragment类似,传入的是vertex的计算结果 例如
struct  v2g
{
    float4  pos    : POSITION;         // vertex position
    float2  uv      : TEXCOORD0;    // vertex uv coordinate
};
不一样的是一次可以处理多个结果
point v2g p[1]
line v2g p[2]
triangle v2g p[3]

返回参数 inout 必须
可以返回3中数据流 PointStream, LineStream, TriangleStream
流中的具体数据类似f2v的数据格式
struct g2f
{
    float4  pos   : POSITION;         // fragment position
    float2  uv     : TEXCOORD0;    // fragment uv coordinate
    float3  dist   : TEXCOORD1;    // distance to each edge of the triangle
};
也是可以返回多个的
inout PointStream<g2f> poiStream
inout LineStream<g2f> linStream
inout TriangleStream<g2f> triStream

Shader==================================================
Shader "Unlit/WithWireframeShder"
{
    Properties
    {
        _MainColor ("Main Color", Color) = (1,1,1,1)
        _LineColor ("Line Color", Color) = (0,0,0,1)
        _Thickness ("Thickness", Float) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        //绘制基础颜色
        Pass
        {           
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
           
            #include "UnityCG.cginc"

            float4 _MainColor;

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
            };
           
            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;
            }
           
            fixed4 frag (v2f i) : SV_Target
            {   
                return _MainColor;
            }
            ENDCG
        }

        //绘制线框
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma geometry geom
            #pragma fragment frag
           
            #include "UnityCG.cginc"

            float4 _LineColor;
            float _Thickness;

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2g
            {
                float4 pos : SV_POSITION;
            };

            struct g2f
            {
                float4    pos        : POSITION;        // fragment position
                float3  dist    : TEXCOORD1;    // distance to each edge of the triangle
            };
           
            v2g vert (appdata v)
            {
                v2g o;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;
            }

            [maxvertexcount(3)]
            void geom(triangle v2g p[3], inout TriangleStream<g2f> triStream)
            {
                //points in screen space
                float2 p0 = _ScreenParams.xy * p[0].pos.xy / p[0].pos.w;
                float2 p1 = _ScreenParams.xy * p[1].pos.xy / p[1].pos.w;
                float2 p2 = _ScreenParams.xy * p[2].pos.xy / p[2].pos.w;
               
                //edge vectors
                float2 v0 = p2 - p1;
                float2 v1 = p2 - p0;
                float2 v2 = p1 - p0;

                //area of the triangle
                float area = abs(v1.x*v2.y - v1.y * v2.x);

                //values based on distance to the edges
                float dist0 = area / length(v0);
                float dist1 = area / length(v1);
                float dist2 = area / length(v2);
               
                g2f pIn;
               
                //add the first point
                pIn.pos = p[0].pos;
                pIn.dist = float3(dist0,0,0);
                triStream.Append(pIn);

                //add the second point
                pIn.pos =  p[1].pos;
                pIn.dist = float3(0,dist1,0);
                triStream.Append(pIn);
               
                //add the third point
                pIn.pos = p[2].pos;
                pIn.dist = float3(0,0,dist2);
                triStream.Append(pIn);
            }
           
            fixed4 frag (g2f input) : SV_Target
            {           
                //find the smallest distance
                float val = min( input.dist.x, min( input.dist.y, input.dist.z));
               
                //calculate power to 2 to thin the line
                val = exp2( -1/_Thickness * val * val );

                //丢弃不在边线上的
                if (val < 0.5f) discard;       

                return _LineColor;
            }
            ENDCG
        }
    }
}




Geometry Shader 实现 Wireframe 绘制边线的Shader的更多相关文章

  1. 【Unity Shader实战】卡通风格的Shader(一)

    写在前面 本系列其他文章: 卡通风格的Shader(二) 呜,其实很早就看到了这类Shader,实现方法很多,效果也有些许不一样.从这篇开始,陆续学习一下接触到的卡通类型Shader的编写. 本篇的最 ...

  2. 【译】Unity3D Shader 新手教程(2/6) —— 积雪Shader

    本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 如果你是一个shader编程的新手,并且你想学到下面这些酷炫的技术,我觉得你可以看看这篇教程: 实现一个积雪效果的 ...

  3. Unity3D Shader官方教程翻译(十九)----Shader语法,编写表面着色器

    Writing Surface Shaders Writing shaders that interact with lighting is complex. There are different ...

  4. Unity3d《Shader篇》绘制圆角图片

    Pass { CGPROGRAM // Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a s ...

  5. Shader剔除像素绘制扇形

    Shader "Custom/Indicator" { Properties { _MainTex("Main Texture", 2D) = "wh ...

  6. 【译】Unity3D Shader 新手教程(4/6) —— 卡通shader(入门版)

    本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 暗黑系 动机 如果你满足以下条件,我建议你阅读这篇教程: 你想了解更多有关表面着色器的细节知识. 你想实现一个入门 ...

  7. 【Unity Shaders】Mobile Shader Adjustment—— 什么是高效的Shader

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  8. Unity shader学习之标准的Unity shader

    包含光照,可处理多个光源,有光照衰减和阴影的shader,代码如下: 转载请注明出处:http://www.cnblogs.com/jietian331/p/7199311.html Shader & ...

  9. Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples

    Surface Shader 光照例子 这里有一些自定义光照模型和Surface Shaders的例子.通常的Surface Shader例子在这里. 由于延迟光照在某些自定义的逐材质光照模型中表现得 ...

随机推荐

  1. TCP传输的三次握手四次挥手策略

    为了准确无误地数据送达目标处,TCP协议采用了三次握手策略.用TCP协议把数据包送出去后,TCP不会对传送后的情况置之不理,它一定会向对方确认是否成功送达.握手中使用了TCP的标志:SYN和ACK 发 ...

  2. 三菱PLC FB库函数调用方法 (Gx Work2版本)

    本文以 GxWorks2 软件为例 1.新建使用标签项目的工程文件 2.从其它库所在工程项目中导入库 3.选择库文件及FB功能块 4.插入FB功能块调用

  3. Python基础之 二

    字符编码: 二进制记录:128 64 32 16 8 4 2 1 1    1   1  1  1 1 1 1  = 8位 ascii 编码:占1个字节8位,只能表示256个符号,主要用于显示英语和其 ...

  4. Spring实战读书笔记

    Spring实战读书笔记 Spring-core Spring之旅 - DI 和 AOP 概念 spring 的Bean容器 spring 的 核心模块 Spring的核心策略 POJO 最小侵入式编 ...

  5. 洛谷 U41572 Portal2

    U41572 Portal2 题目背景 某地ENLIGHTENED的XM研究所正在研究Portal的处理法则,想要揭示XM能量的来源以及应用XM能量.ENLIGHTENED的首席科学家Jacks发现其 ...

  6. Linux下使用make install安装的软件如何卸载

    如果是Ubuntu的系统,那么可以使用checkinstall来生成deb包来安装,然后卸载 参考:http://blog.sina.com.cn/s/blog_4178f4bf0101cmt7.ht ...

  7. Android GIS开发系列-- 入门季(9) 定位当前的位置

    利用MapView定位当前的位置 这里要用到Arcgis中的LocationDisplayManager这个类,由于比较简单.直接上代码: LocationDisplayManager locatio ...

  8. FlashBuilder 4.7 非正常关闭导致的不能启动的解决的方法

    停电.或者卡死.FB就不能正常启动了. 以下是老外给出的方法,好用: 进入.metadata/.plugins/org.eclipse.core.resources 文件夹 删除.snap文件 假设是 ...

  9. yarn 和 npm 的区别

    npm 与 yarn 命令对比 npm yarn npm install yarn install (N/A) yarn install --flat (N/A) yarn install --har ...

  10. 黑马day13 分页思路&amp;实现

    分页的总体思想: 分页包含什么: 1.当前页,每页显示的记录数,总的记录数,总的页码,集合List存放的是JavaBean,首页, 尾页,上一页,下一页 传递的參数:当前页,每页显示的记录数.这两个本 ...