【Shader】简单的屏幕喷血渐溶效果

一般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);

完整的项目资源下载: 点击打开链接

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值