zoukankan      html  css  js  c++  java
  • Geometry Shader 实现 Wireframe 绘制边线的Shader

    最终效果:

    参考了一个免费插件

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

    基础知识======================================
    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
            }
        }
    }




  • 相关阅读:
    /etc/sysctl.conf 控制内核相关配置文件
    python 并发编程 非阻塞IO模型
    python 并发编程 多路复用IO模型
    python 并发编程 异步IO模型
    python 并发编程 阻塞IO模型
    python 并发编程 基于gevent模块 协程池 实现并发的套接字通信
    python 并发编程 基于gevent模块实现并发的套接字通信
    python 并发编程 io模型 目录
    python 并发编程 socket 服务端 客户端 阻塞io行为
    python 并发编程 IO模型介绍
  • 原文地址:https://www.cnblogs.com/Hichy/p/8399502.html
Copyright © 2011-2022 走看看