一般FPS中的屏幕溅血效果可以使用UI贴图制作,简单,缺点是效果生硬,不够逼真。这边提供一种方案思路,可以随机生成血液喷溅并慢慢溶解的效果。
首先是全屏特效的实现。可以用OnPostRender实现,但是消耗太大,有点浪费。我们可以在相机前放置一个Quad面片,然后其渲染至整个屏幕。再在这个面片上进行纹理绘制即可。
v2f vert(appdata_base v)
{
v2f o;
o.pos = v.vertex;
o.vertex = fixed4(v.vertex.x * 2, v.vertex.y * 2, 0, 1);
return o;
}
然后就正题:随机的血液效果了。根据屏幕坐标采集噪声图像值,跟颜色叠加,将半透的alpha值剔除即可。
首先是噪声生成。这边山寨了一个超快的value噪声函数。https://www.shadertoy.com/view/4sfGzS
float noise(float3 x)
{
x *= 4.0;
float3 p = floor(x);
float3 f = frac(x);
f = f*f*(3.0 - 2.0*f);
float2 uv = (p.xy + float2(37.0, 17.0)*p.z) + f.xy;
float2 rg = tex2D(_NoiseOffsets, (uv + 0.5) / 256.0).yx;
return lerp(rg.x, rg.y, f.z);
}
float noise_sum(float3 p)
{
float f = 0.0;
f += (1.0000 * noise(p)); p = 2.0 * p;
f += (0.5000 * noise(p)); p = 2.0 * p;
f += (0.2500 * noise(p)); p = 2.0 * p;
f += (0.1250 * noise(p)); p = 2.0 * p;
//f += 0.06255 * noise(p);
return f;
}
_NoiseOffsets是一个噪声图像,可以在这边下载:http://www.blog.sirenix.net/s/NoiseOffsets.asset
然后,简单的颜色叠加即可:
fixed4 frag(v2f i) :SV_Target
{
fixed4 c;
c = _Color * noise_sum(i.pos * _NoiseSize + _NoisePos);
if (c.a <= _Fade)
{
c.a = 0f;
}
return c;
}
对NoisePos随机取值就可以随机出不同的血液效果,改变Color的alpha值,我们就能慢慢溶解绘制出来的血液。
public class CamBlood : MonoBehaviour
{
float startVal;
Material curMat;
int propIdColor;
int propIdNoisePos;
float durTime;
float curTime;
static CamBlood _inst;
public static CamBlood Inst
{
get
{
if (_inst == null)
{
GameObject gobj = Instantiate(Resources.Load<GameObject>("Prefabs/effect/CamBlood")) as GameObject;
_inst = gobj.GetComponent<CamBlood>();
}
return _inst;
}
}
void Awake()
{
curMat = renderer.sharedMaterial;
propIdColor = Shader.PropertyToID("_Color");
propIdNoisePos = Shader.PropertyToID("_NoisePos");
}
void Update()
{
if (curTime <= durTime)
{
//显示中
curTime += Time.deltaTime;
float val = (1 - (curTime / durTime)) * this.startVal;
curMat.SetColor(propIdColor, new Color(0.19f, 0.03f, 0.03f, val));
}
else if(durTime > 0)
{
curMat.SetColor(propIdColor, new Color(0.19f, 0.03f, 0.03f, 0f));
}
}
public void Create(Camera camera, float val, float durTime)
{
this.startVal = val;
_inst.transform.parent = camera.transform;
_inst.transform.localPosition = new Vector3(0f, 0f, 1f);
_inst.transform.localEulerAngles = Vector3.zero;
curMat.SetVector(propIdNoisePos, new Vector4(0, 0, Random.Range(0f, 1f), 1));
curMat.SetColor(propIdColor, new Color(0.19f, 0.03f, 0.03f, val));
this.durTime = durTime;
curTime = 0f;
}
}
需要创建时,调用即可
CamBlood.Inst.Create(cam, startVal, dur);
完整的项目资源下载: 点击打开链接