相交高亮,即是把模型间交界线用别的颜色给标记出来。是深度图的一个应用,我更愿意把它提出来当做一种shader模型(就像边缘高亮Rim一样)来记忆。
一、原理
得到当前模型片元的深度 Z 0 Z_{0} Z0,和深度图中该片元所在位置的深度 Z d e p t h T e x t u r e Z_{depthTexture} ZdepthTexture。两者相减得到深度差
Z d i f f Z_{diff} Zdiff = | Z 0 − Z d e p t h T e x t u r e Z_{0} - Z_{depthTexture} Z0−ZdepthTexture|,当 Z d i f f Z_{diff} Zdiff < Z i n t e r s e c t Z_{intersect} Zintersect (其中 Z i n t e r s e c t Z_{intersect} Zintersect > 0),则有相交。
二、案例
Shader "Unlit/IntersectHightLight"
{
Properties
{
_Color ("Color",Color) = (0,0,0,0)
_IntersectWidth("Intersect Width",Range(0,5)) = 0.05 //相交宽度 Zintersect
_IntersectColor("Intersect Color",Color) = (0,0,0,0) //交界颜色
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue" = "Transparent"}
LOD 100
Pass
{
//为了方便观察相交情况,设置半透,双面渲染
ZWrite Off
Cull off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float Z0 : TEXCOORD0;
float4 scrPos : TEXCOORD1;
float4 vertex : SV_POSITION;
};
fixed4 _Color;
//深度图,前提是摄像机设置了 Camera.main.depthTextureMode = DepthTextureMode.Depth;
//否则没有哦
sampler2D _CameraDepthTexture;
float _IntersectWidth;
fixed4 _IntersectColor;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
COMPUTE_EYEDEPTH(o.Z0);// 在相机空间把顶点的深度存入ZO
o.scrPos = ComputeScreenPos(o.vertex);//先把顶点在屏幕空间的位置存起来,用于片元着色器中获取深度图的深度
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//以下就是获取该片元在相机空间的深度值
float ZdepthTexture = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture,UNITY_PROJ_COORD(i.scrPos)));
float Zdiff = saturate(_IntersectWidth - abs(ZdepthTexture - i.Z0));//用模型的改片元的深度值 和 深度图的深度值 取差
return lerp(_Color,_IntersectColor,Zdiff); //为了效果比较柔和,做了差值处理
}
ENDCG
}
}
}
效果图:
相交高亮可以用到游戏里很多地方,比如能量圈,激光扫描等等(其实使用场景的是不确定的,但这个相交高亮的特色是确定,我们应该在了解了一项技术的各项特色之后去适应不确定的场景,这点很重要。。。)
有关深度图的知识请参考:
Unity Shader - 深度图基础及应用
有趣的深度图:可见性问题的解法
神奇的深度图:复杂的效果,不复杂的原理
Camera’s Depth Texture