Unity3D NGUI动态生成模糊背景图

先上效果。

 

制作原理:模糊的部分是用UITexture,前面是一个UISprite。用主摄像机渲染出一张纹理,把这张纹理模糊处理,把这张纹理赋值给UITexture。

 

脚本代码

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(UITexture))]
public class BlurTextureMaker : MonoBehaviour {

	public int iterations = 3;

	public float blurSpread = 0.6f;

	public Shader blurShader = null;

	

	static Material m_Material = null;

	public Camera camera;

	private UITexture mTexture;

	private RenderTexture mRT;
	protected Material material
	{
		get
		{
			if (m_Material == null)
			{
				m_Material = new Material(blurShader);
				m_Material.hideFlags = HideFlags.DontSave;
			}
			return m_Material;
		}
	}

	protected void Awake()
	{
		mTexture = GetComponent<UITexture>();
	}

	protected void Start()
	{
		// Disable if we don't support image effects
		if (!SystemInfo.supportsImageEffects)
		{
			enabled = false;
			return;
		}
		// Disable if the shader can't run on the users graphics card
		if (!blurShader || !material.shader.isSupported)
		{
			enabled = false;
			return;
		}




		int rtWidth = (int)(NGUITools.screenSize.x / 4);
		int rtHeight = (int)(NGUITools.screenSize.y / 4);

		mRT = RenderTexture.GetTemporary(rtWidth, rtHeight, 0, RenderTextureFormat.Default);

		mTexture.mainTexture = Generate();
	}

	protected void OnDestroy()
	{
		if (null != mRT)
		{
			RenderTexture.ReleaseTemporary(mRT);
		}
	}

	// Performs one blur iteration.
	public void FourTapCone(RenderTexture source, RenderTexture dest, int iteration)
	{
		float off = 0.5f + iteration * blurSpread;
		Graphics.BlitMultiTap(source, dest, material,
			new Vector2(-off, -off),
			new Vector2(-off, off),
			new Vector2(off, off),
			new Vector2(off, -off)
		);
	}

	// Downsamples the texture to a quarter resolution.
	private void DownSample4x(RenderTexture source, RenderTexture dest)
	{
		float off = 1.0f;
		Graphics.BlitMultiTap(source, dest, material,
			new Vector2(-off, -off),
			new Vector2(-off, off),
			new Vector2(off, off),
			new Vector2(off, -off)
		);
	}

	// Called by the camera to apply the image effect
	void RenderImage(RenderTexture source, RenderTexture destination)
	{
		int rtW = source.width / 4;
		int rtH = source.height / 4;
		RenderTexture buffer = RenderTexture.GetTemporary(rtW, rtH, 0);

		// Copy source to the 4x4 smaller texture.
		DownSample4x(source, buffer);

		// Blur the small texture
		for (int i = 0; i < iterations; i++)
		{
			RenderTexture buffer2 = RenderTexture.GetTemporary(rtW, rtH, 0);
			FourTapCone(buffer, buffer2, i);
			RenderTexture.ReleaseTemporary(buffer);
			buffer = buffer2;
		}
		Graphics.Blit(buffer, destination);

		RenderTexture.ReleaseTemporary(buffer);
	}

	public RenderTexture Generate()
	{
		int rtWidth = (int) (NGUITools.screenSize.x/4);
        int rtHeight = (int) (NGUITools.screenSize.y/4);

		var tex = RenderTexture.GetTemporary(rtWidth, rtHeight, 0, RenderTextureFormat.Default);

		camera.targetTexture = tex;
		camera.Render();
		camera.targetTexture = null;
		
		
		RenderImage(tex, mRT);

		RenderTexture.ReleaseTemporary(tex);

		return mRT;
	}

	[ContextMenu("Sample")]
	public void Sample()
	{
		var tex = GetComponent<UITexture>();
		tex.mainTexture = Generate();

	}
}

  

//Shader代码

Shader "Hidden/BlurEffectConeTap" {
	Properties { _MainTex ("", any) = "" {} }
	SubShader { 
		Pass {
			ZTest Always Cull Off ZWrite Off Fog { Mode Off }
			SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant alpha}
			SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
			SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
			SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
		}
	}
	CGINCLUDE
	#include "UnityCG.cginc"
	struct v2f {
		float4 pos : SV_POSITION;
		half2 uv : TEXCOORD0;
		half2 taps[4] : TEXCOORD1; 
	};
	sampler2D _MainTex;
	half4 _MainTex_TexelSize;
	half4 _BlurOffsets;
	v2f vert( appdata_img v ) {
		v2f o; 
		o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
		o.uv = v.texcoord - _BlurOffsets.xy * _MainTex_TexelSize.xy; // hack, see BlurEffect.cs for the reason for this. let's make a new blur effect soon
		o.taps[0] = o.uv + _MainTex_TexelSize * _BlurOffsets.xy;
		o.taps[1] = o.uv - _MainTex_TexelSize * _BlurOffsets.xy;
		o.taps[2] = o.uv + _MainTex_TexelSize * _BlurOffsets.xy * half2(1,-1);
		o.taps[3] = o.uv - _MainTex_TexelSize * _BlurOffsets.xy * half2(1,-1);
		return o;
	}
	half4 frag(v2f i) : SV_Target {
		half4 color = tex2D(_MainTex, i.taps[0]);
		color += tex2D(_MainTex, i.taps[1]);
		color += tex2D(_MainTex, i.taps[2]);
		color += tex2D(_MainTex, i.taps[3]); 
		return color * 0.25;
	}
	ENDCG
	SubShader {
		 Pass {
			  ZTest Always Cull Off ZWrite Off
			  Fog { Mode off }      

			  CGPROGRAM
			  #pragma fragmentoption ARB_precision_hint_fastest
			  #pragma vertex vert
			  #pragma fragment frag
			  ENDCG
		  }
	}
	Fallback off
}

  

posted @ 2016-05-03 18:48  MrBlue  阅读(4477)  评论(3编辑  收藏  举报