效果图,上边是正常遮挡,下边是修改后的,遮挡部分半透明高亮显示出来
- 默认情况下,模型如果有一部分被其他物体遮挡,在进行深度测试的时候是不会被通过的,所以最终不会被渲染出来。如果想让被遮挡的部分渲染出来,那就只能让他通过深度测试,然后跟已存在的像素进行混合,从而产生半透明效果。
- 模型未被遮挡的部分走正常渲染流程即可。
Shader "Custom/OcclusionShader"
{
Properties
{
//part of being occlusion
_Color("Occlusion Color", Color) = (0,1,1,1)
_Width("Occlusion Width", Range(0, 10)) = 1
_Intensity("Occlusion Intensity",Range(0, 10)) = 1
//ordinary part
_Albedo("Albedo", 2D) = "white"{}
_Specular("Specular (RGB-A)", 2D) = "black"{}
_Normal("Nromal", 2D) = "bump"{}
_AO("AO", 2D) = "white"{}
}
上半部分的变量用于控制被遮挡部分。_Color用于控制颜色;_Width控制边缘高亮的宽度;_Intensity控制高亮的亮度。
下半部分是正常PBR Specular工作流的部分,为了节省资源,我把Shininess放在了_Specular的a通道里。
- 我们想要被遮挡的部分透明显示,所以把shader的渲染序列设为Transparent
- 我们想要被遮挡的部分仍然通过深度测试,所以把测试方式改为Greater,也就是说当前面有物体挡住它的时候,它就会显示出来
- 我们只需要使用普通的透明混合方式即可,所以使用Blend SrcAlpha OneMinusSrcAlpha
- 考虑到性能,我们在这一部分使用顶点-片段着色器。顶点着色器中使用内置的appdata_base结构体作为输入,然后输出包含“裁切空间顶点坐标”、“世界空间视线向量”和“世界空间法线向量”的v2f结构体。
- 在片段着色器中,我们把视线向量和法线向量进行点乘,然后使用saturate函数得到范围[0,1]内的数值,从而得到中间白边缘黑的效果。1减去这个结果,得到反相效果,也就是边缘白,中间黑的效果。使用pow函数,控制边缘的宽度,然后乘以一个变量控制边缘最终的亮度,最终输入给透明度,实现半透效果。
- 把_Color输出给颜色。