UnityShader Stencil 模板测试 线框 网格

30 篇文章 2 订阅

https://blog.csdn.net/u011047171/article/details/46928463#t4
https://github.com/haxflying/QuadWireFrameShader/edit/master/QuadWireframe.shader
https://www.jianshu.com/p/e95e6507659c
https://docs.unity3d.com/cn/current/Manual/SL-Stencil.html

在这里插入图片描述

注意:蒙版测试和Unity物体的渲染顺序一样,都是从摄像机往天空盒方向渲染的(从前往后)

if(ref & readmask (op) buff & readmask)
{
	通过
}else
{
	失败
}

灵魂画师😄在这里插入图片描述

这个可以在场景里直接显示网格
Object

Shader "Z/QuadWireframe"
{
    Properties
    {
        [HDR]_LineColor("Line Color", Color) = (1,1,1,1)
        [HDR]_BackColor("Back Color", Color) = (0,0,0,0)
        _WireThickness ("Wire Thickness", RANGE(0, 800)) = 100
        [Toggle(ENABLE_DRAWQUAD)]_DrawQuad("Draw Quad", Float) = 0
        [Enum(UnityEngine.Rendering.CullMode)] _Cull ("Cull Mode", Float) = 2

        _MainTex ("Base (RGB)", 2D) = "white" {}
    }

    SubShader
    {
        Tags { "Queue" = "Transparent"  "IgnoreProjection" = "True" "RenderType" = "Transparent" }
        // Each color represents a meter.
        Blend SrcAlpha OneMinusSrcAlpha
        Cull [_Cull]
        ZWrite Off

        Pass
        {
            Stencil {
                Ref 1
                Comp Equal
            } 
            // Wireframe shader based on the the following
            // http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf

            CGPROGRAM
            #pragma target 4.0
            #pragma multi_compile __ ENABLE_DRAWQUAD
            #pragma vertex vert
            #pragma geometry geom
            #pragma fragment frag

            #include "UnityCG.cginc"

            float _WireThickness;
            half4 _LineColor;

            struct appdata
            {
                float4 vertex : POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2g
            {
                float4 projectionSpaceVertex : SV_POSITION;
                float4 worldSpacePosition : TEXCOORD1;
                float4 vertexPos : TEXCOORD2;
                UNITY_VERTEX_OUTPUT_STEREO
            };

            struct g2f
            {
                float4 projectionSpaceVertex : SV_POSITION;
                float4 worldSpacePosition : TEXCOORD0;
                float4 dist : TEXCOORD1;
                int max : TEXCOORD2;
                UNITY_VERTEX_OUTPUT_STEREO
            };
            
            v2g vert (appdata v)
            {
                v2g o;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                o.projectionSpaceVertex = UnityObjectToClipPos(v.vertex);
                o.worldSpacePosition = mul(unity_ObjectToWorld, v.vertex);
                o.vertexPos = v.vertex;
                return o;
            }
            
            [maxvertexcount(3)]
            void geom(triangle v2g i[3], inout TriangleStream<g2f> triangleStream)
            {
                float2 _p0 = i[0].projectionSpaceVertex.xy / i[0].projectionSpaceVertex.w;
                float2 _p1 = i[1].projectionSpaceVertex.xy / i[1].projectionSpaceVertex.w;
                float2 _p2 = i[2].projectionSpaceVertex.xy / i[2].projectionSpaceVertex.w;

                float3 p0 = i[0].vertexPos;
                float3 p1 = i[1].vertexPos;
                float3 p2 = i[2].vertexPos;

                float2 edge0 = _p2 - _p1;
                float2 edge1 = _p2 - _p0;
                float2 edge2 = _p1 - _p0;

                float s0 = length(p2 - p1);
                float s1 = length(p2 - p0);
                float s2 = length(p1 - p0);

                // To find the distance to the opposite edge, we take the
                // formula for finding the area of a triangle Area = Base/2 * Height, 
                // and solve for the Height = (Area * 2)/Base.
                // We can get the area of a triangle by taking its cross product
                // divided by 2.  However we can avoid dividing our area/base by 2
                // since our cross product will already be double our area.
                float area = abs(edge1.x * edge2.y - edge1.y * edge2.x);
                float wireThickness = 800 - _WireThickness;
                int max = 0;

                #if ENABLE_DRAWQUAD
                    if(s1 > s0)
                    {
                        if(s1 > s2)
                        max = 1;
                        else
                        max = 2;
                    }
                    else if(s2 > s0)
                    {
                        max = 2;
                    }				
                #endif
                g2f o;

                o.worldSpacePosition = i[0].worldSpacePosition;
                o.projectionSpaceVertex = i[0].projectionSpaceVertex;
                o.dist.xyz = float3( (area / length(edge0)), 0.0, 0.0) * wireThickness * o.projectionSpaceVertex.w;
                o.dist.w = 1.0 / o.projectionSpaceVertex.w;
                o.max = max;
                UNITY_TRANSFER_VERTEX_OUTPUT_STEREO(i[0], o);
                triangleStream.Append(o);

                o.worldSpacePosition = i[1].worldSpacePosition;
                o.projectionSpaceVertex = i[1].projectionSpaceVertex;
                o.dist.xyz = float3(0.0, (area / length(edge1)), 0.0) * wireThickness * o.projectionSpaceVertex.w;
                o.dist.w = 1.0 / o.projectionSpaceVertex.w;
                o.max = max;
                UNITY_TRANSFER_VERTEX_OUTPUT_STEREO(i[1], o);
                triangleStream.Append(o);

                o.worldSpacePosition = i[2].worldSpacePosition;
                o.projectionSpaceVertex = i[2].projectionSpaceVertex;
                o.dist.xyz = float3(0.0, 0.0, (area / length(edge2))) * wireThickness * o.projectionSpaceVertex.w;
                o.dist.w = 1.0 / o.projectionSpaceVertex.w;
                o.max = max;
                UNITY_TRANSFER_VERTEX_OUTPUT_STEREO(i[2], o);
                triangleStream.Append(o);
            }

            fixed4 frag (g2f i) : SV_Target
            {				
                float minDistanceToEdge;// = min(i.dist[0], min(i.dist[1], i.dist[2])) * i.dist[3];
                #if ENABLE_DRAWQUAD
                    if(i.max == 0)
                    minDistanceToEdge = min(i.dist[1], i.dist[2]);
                    else if(i.max == 1)
                    minDistanceToEdge = min(i.dist[0], i.dist[2]);
                    else 
                    minDistanceToEdge = min(i.dist[0], i.dist[1]);
                #else
                    minDistanceToEdge = min(i.dist[0], min(i.dist[1], i.dist[2])) * i.dist[3];
                #endif
                // Early out if we know we are not on a line segment.
                if(minDistanceToEdge > 0.9)
                {
                    return fixed4(0,0,0,0);
                }

                // Smooth our line out
                float t = exp2(-2 * minDistanceToEdge * minDistanceToEdge);
                fixed4 wireColor = _LineColor;

                fixed4 finalColor = lerp(float4(0,0,0,0), wireColor, t);
                finalColor.a = t;

                return finalColor;
            }
            ENDCG
        }

        Pass { 
            
            Stencil {
                Ref 1
                Comp NotEqual
            } 
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            
            #include "UnityCG.cginc"
            
            struct appdata_t {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
                
            };
            
            struct v2f {
                float4 vertex : SV_POSITION;
                half2 texcoord : TEXCOORD0;
                
                UNITY_FOG_COORDS(1)
            };
            
            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            v2f vert (appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.texcoord);
                UNITY_APPLY_FOG(i.fogCoord, col);
                UNITY_OPAQUE_ALPHA(col.a);
                
                return col;
            }
            ENDCG
        }
    }
}

Quad

Shader "Custom/UnlitStencilMaskVF" {
    SubShader {
        Tags { "RenderType"="Opaque" "Queue"="Geometry-1"}
        
        CGINCLUDE

        struct appdata {
            float4 vertex : POSITION;
        };

        struct v2f {
            float4 pos : SV_POSITION;
        };

        v2f vert(appdata v) {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex);
            return o;
        }

        half4 frag(v2f i) : SV_Target {
            return half4(1,1,0,1);
        }
        
        ENDCG
        
        Pass {
            
            ColorMask 0
            ZWrite Off
            
            Stencil
            {
                Ref 1
                Comp Always
                Pass Replace
            }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            ENDCG
        }
        
        
    } 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值