您的位置:首页 > 移动开发 > Unity3D

[unity3d] 模型XRay效果实现

2017-09-17 15:37 375 查看
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"
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unity3d shader