使用Projector实现纹理投射
转载注明出处: https://blog.****.net/winchyy/article/details/51564489
游戏中,我们经常需要实现将纹理投射到场景中其他物体上的效果,如地上的光环、石块上的logo、水印等。很多情况下我们可以通过灯光或者其他方式达到我们想要的效果,但是Unity已经为我们提供了一种更加便捷高效的实现方式,那就是Projector组件。
最终效果预览
准备工作
首先创建工程,通过Assets->Import Package->Effects导入标准资源库中的特效素材,如下图所示。如果安装Unity时没有安装标准资源库,可以到这里单独下载并安装。
导入资源后,Project中将出现下图中的结构:
接下来就可以在场景中加入必要的元素了。
应用Projector组件
将BlobShadowProjector(Standard Shader Gallery -> Effects -> Projectors -> Prefabs)拖入场景中,Inspector面板如图:
BlobShadowProjector实现的是通过Projector组件在物体上投射一个圆形的阴影。将上图中Cookie改成我们需要的图片(注意图片属性中Alpha from Grayscale需要勾选,Wrap mode选择Clamp,当然你可以尝试不同选择看实际效果),但仍然存在不少问题,如png图片中的透明部分会被渲染成黑色,场景中有不明条纹等。
Projector的原理是为其frustum范围内的物体增加一个Pass,将我们在Projector中定义的材质渲染出来。为了解决上面所说的问题,我们可以创建自己的Shader和材质。
首先,复制Standard Shader Gallery -> Effects -> Projectors -> ProjectorMultiply,另存为ProjectorCustom,修改如下:
Shader "Projector/Custom" {
Properties{
_ShadowTex("Cookie", 2D) = "gray" {}
_FalloffTex("FallOff", 2D) = "white" {}
}
Subshader{
Tags{ "Queue" = "Transparent" }
Pass{
ZWrite Off
ColorMask RGB
//Blend DstColor Zero
Blend SrcAlpha OneMinusSrcAlpha
Offset -1, -1
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct v2f {
float4 uvShadow : TEXCOORD0;
float4 uvFalloff : TEXCOORD1;
UNITY_FOG_COORDS(2)
float4 pos : SV_POSITION;
};
float4x4 _Projector;
float4x4 _ProjectorClip;
v2f vert(float4 vertex : POSITION)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, vertex);
o.uvShadow = mul(_Projector, vertex);
o.uvFalloff = mul(_ProjectorClip, vertex);
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
sampler2D _ShadowTex;
sampler2D _FalloffTex;
fixed4 frag(v2f i) : SV_Target
{
fixed4 texS = tex2Dproj(_ShadowTex, UNITY_PROJ_COORD(i.uvShadow));
//texS.a = 1.0-texS.a;
//fixed4 texF = tex2Dproj(_FalloffTex, UNITY_PROJ_COORD(i.uvFalloff));
//lerp(fixed4(1, 1, 1, 0), texS, texF.a);
fixed4 res = texS;
UNITY_APPLY_FOG_COLOR(i.fogCoord, res, fixed4(1,1,1,1));
return res;
}
ENDCG
}
}
}
注释的部分为修改之前的代码
新建一个材质并将Shader选择为Projector/Custom,勾选图片的Alpha is Transparent,将新材质作为Projector组件的Material,并勾选Projector组件的Orthographic复选框,得到如下效果:
我们发现图片不仅投射到地面和方块上,也投射到了人物上,这显然不是我们想要的效果,不过这个问题处理起来很简单,只需要新建一个Player的Layer,将人物的Layer选成Player,然后将Projector的Ignore Layers设置成Player得到了我们的最终效果了。
总结
Projector是一个非常有用的组件,除了我们上面实现的效果,还能用来廉价的实现投影(如我们最开始使用的BlobShadowProjector)、特殊光效(可以用来代替Cookie或者范围光,但是更加高效)等效果,通过尝试不同的设置和不同的Shader,我们还会得到更多有意思的效果。