[unity3d] 模型XRay效果实现

XRay效果常常用来显示被墙体及其它物体遮挡的物体的轮廓,效果一般如下图所示,如人物身上的蓝色部分。



算法原理:

使用两个Pass对人物进行绘制,其它第一个Pass正常对人物进行绘制,第二个pass使用半透明模式根据Z-Test绘制被遮挡的部分。引擎对不透明物体(Opaque)和半透明物体进行分开绘制,并且一定是先绘制Opaque物体,然后再绘制半透明物体,所以可以在第二Pass中根据已经绘制Opaque物体的Z值来判断物体的某一部分是否需要再次绘制,只有Z-Buffer中的值大于当前的Z值才说明该部分被遮挡。判断条件为:

ztest greater


Shader制作:

1,创建一个Surface Shader,  命名XrayEffect。

2,在XRayEffect的基础上增加一个pass, 代码如下:

        

pass{
            Blend SrcAlpha OneMinusSrcAlpha
                zwrite off
                ztest greater 

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag 
            #pragma target 3.0

            #include "UnityCG.cginc"


            struct v2f{
            float4 pos:POSITION;

            };

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

            float4 frag(v2f IN):color{

            float4 col=float4(0,0,1,0.5f);
            return col;
            }


            ENDCG
        }

3,将模型的shader替换成XRayEffect,效果如下,明显感觉到效果不对,由于在编辑器模式下该模型并未被其它物体遮挡,但是还是绘制出了Xray效果,显然这不并是我们需要的,这是由于模型自身部分的遮挡导致的。


4,为了去除上一步看到的部分,我们使用Stencil进行过滤,该Shader的第一个Pass中我们向Stencil Buffer中写入一个值254,在Xray的pass中,如果stencil的值为254,则不再绘制效果如下:


附完整Shader代码:

Shader "Custom/XRayEffect" {
	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_Glossiness ("Smoothness", Range(0,1)) = 0.5
		_Metallic ("Metallic", Range(0,1)) = 0.0
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200

		Stencil {  
                Ref 254 
                Comp Always
                Pass Replace
                ZFail Keep
            }
		
		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard fullforwardshadows

		// Use shader model 3.0 target, to get nicer looking lighting
		#pragma target 3.0

		sampler2D _MainTex;

		struct Input {
			float2 uv_MainTex;
		};

		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
		// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
		// #pragma instancing_options assumeuniformscaling
		UNITY_INSTANCING_CBUFFER_START(Props)
			// put more per-instance properties here
		UNITY_INSTANCING_CBUFFER_END

		void surf (Input IN, inout SurfaceOutputStandard o) {
			// Albedo comes from a texture tinted by color
			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c.rgb;
			// Metallic and smoothness come from slider variables
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;
		}
		ENDCG

		pass{
	        Blend SrcAlpha OneMinusSrcAlpha
	            zwrite off
	            ztest greater 


	        Stencil {  
                Ref 254         
                Comp NotEqual             
                Pass Keep 
                ZFail Keep
            }


	        CGPROGRAM
	        #pragma vertex vert
	        #pragma fragment frag 
	        #pragma target 3.0

	        #include "UnityCG.cginc"


	        struct v2f{
	        float4 pos:POSITION;

	        };

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

	        float4 frag(v2f IN):color{

	        float4 col=float4(0,0,1,0.5f);
	        return col;
	        }


	        ENDCG
        }
	}
	FallBack "Diffuse"
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值