制作3d人物控制时,经常遇见镜头撞墙缩到角色模型内的“卡视角”现象。但在部分场景中是突发的卡视角会破坏游戏体验,所以有种方案是将遮挡人物的物体透明化消隐掉。
最近看见碧蓝幻想relink中的场景抖动消隐方式比较感兴趣,所以试着实现一下shader
效果如右图,抖动
矩阵设置比较简单所以点阵比较规则
关键方法就是在片元着色器里使用clip函数弃置部分片元
screenPos是片元在屏幕空间的坐标
Properties {
_Dither ("Dither",Range(0, 1)) = 0.5//抖动阈值
}
fixed4 frag(v2f i) : SV_Target {
//抖动剔除像素
float2 screenPos = (i.screenPos.xy / i.screenPos.w) * _ScreenParams.xy;//屏幕像素坐标
float DITHER_THRESHOLDS[4][4] =
{//抖动矩阵,就是不透明度矩阵
1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
};
clip(_Dither - DITHER_THRESHOLDS[floor(fmod(screenPos.x, 4))][floor(fmod(screenPos.y, 4))]);
//……
消隐的实现比较简单,但加上阴影就有出现问题了
接受阴影是SHADOW_COORDS(),TRANSFER_SHADOW(o);,UNITY_LIGHT_ATTENUATION(atten, i, worldPos);三剑客
投射阴影是自定pass
// 投射阴影
Pass {
Name "Caster"
Tags { "LightMode" = "ShadowCaster" }//阴影投射模式
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster//支持阴影投射
#include "UnityCG.cginc"
//float _Dither;
struct v2f {
//float4 screenPos : TEXCOORD0;//屏幕坐标,[0,1]
V2F_SHADOW_CASTER;//宏定义的结构体,包含阴影投射所需的顶点数据
};
v2f vert( appdata_base v )
{
v2f o;
//o.screenPos = ComputeScreenPos(v.vertex);//齐次屏幕空间坐标,在[0,1]之间
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)//是一个宏,它用于计算并设置o结构体中阴影投射所需的法线和偏移信息。
return o;
}
float4 frag( v2f i ) : SV_Target
{
抖动剔除像素
//float2 screenPos = (i.screenPos.xy / i.screenPos.w) * _ScreenParams.xy;//屏幕像素坐标
//float DITHER_THRESHOLDS[4][4] =
//{
// 1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
// 13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
// 4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
// 16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
//};//抖动阈值
//clip(_Dither - DITHER_THRESHOLDS[floor(fmod(screenPos.x, 4))][floor(fmod(screenPos.y, 4))]);
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
设定一,材质渲染路径<2500,有深度图,能接受阴影但看不见柱后的阴影,虽然柱子理应是“透明”的
设定二,渲染路径>2500,无深度图,不能接受阴影,但可以看见柱后阴影,当_Dither抖动阈值设为1时也没法接受阴影了
设定三,渲染路径<2500,把投射阴影pass里也添加抖动剔除,结果是符合想象但走样严重
最终的妥协方案是两个材质,
未遮挡人物不产生抖动消隐就是正常不透明物体的渲染路径能接受阴影;
遮挡人物产生消隐了切换渲染路径为Transparent的材质,虽不能接受阴影但无伤大雅,重要是透过这个物体看人物及其他物体的阴影是正常的