静态毛玻璃渲染效果

静态毛玻璃渲染效果


最近项目需要优化毛玻璃渲染效果,之前是使用的线性Shader来实现的。需求是使用高斯模糊来实现,然后做出了第一版纯使用Shader来实现,发现效率不佳,便得以引申,使用了Unity的Graphics 来进行图像处理。下面来介绍实现思想:
1.准备工作,需要实现一个高斯模糊毛玻璃的Shader(网上有很多),并且创建一个对应的材质球(在代码处理图片的时候会用到)
2. 通过RenderTexture来将需要毛玻璃化的场景或者界面渲染一张图(注意这里需要理清逻辑,盖在毛玻璃上层的界面如果跟毛玻璃是一个整体,可先隐藏然后处理完毕后再显示)。

	float scale = 0.4f;
    int mScreenx = (int)FairyGUI.StageCamera.main.pixelWidth;
    int mScreeny = (int)FairyGUI.StageCamera.main.pixelHeight;
	var rt = RenderTexture.GetTemporary((int)(mScreenx * scale), (int)(mScreeny * scale), 16, RenderTextureFormat.ARGB32);
	//这里实例化材质
	materialBlur = GameObject.Instantiate(Resources.Load<Material>("Material/GaussianBlur"), gameObject.transform) as Material;
    FairyGUI.StageCamera.main.targetTexture = rt;
    FairyGUI.StageCamera.main.RenderDontRestore();
    FairyGUI.StageCamera.main.targetTexture = null;
    
    for (int i = 0; i < iteration; i++)
    {
        Graphics.Blit(rt, rt2, materialBlur, 0);
    	Graphics.Blit(rt2, rt, materialBlur, 1);
    }
    
    float _x = screenPos.x;
    float _y = screenPos.y;
    NTexture tex = new NTexture(rt, new Rect(_x, _y, mScreenx * scale, mScreeny * scale));
    graphics.texture = tex;

以上就是核心代码了
一下是Shader代码

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Windplay/UI/Gaussian Blur" {
	Properties {
		[HideInInspector]_MainTex ("Base (RGB)", 2D) = "white" {}
		_BlurSize ("Blur Size", Float) = 4.0
		_TextureSize ("_TextureSize",Range(0.0001,0.004)) = 0.00208
		_Weight("Weight",Range(1,100)) = 100
        _BlurRadius ("_BlurRadius",Range(1,30) ) = 17
	}
	SubShader {
		Tags {"Queue" = "Transparent+200" "RenderType" = "Opaque" }
		CGINCLUDE
		
		#include "UnityCG.cginc"
		
		sampler2D _MainTex;  
		half4 _MainTex_TexelSize;
		float _BlurSize;
		float _Weight;
		float _TextureSize;
		int _BlurRadius;
		struct appdata
		{
			float4 vertex : POSITION;
			float2 uv : TEXCOORD0;
		};

		struct v2f {
			float4 pos : SV_POSITION;
			float4 texuv:TEXCOORD0;
		};
		  
		v2f vertBlurVertical(appdata v) {
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			#if UNITY_UV_STARTS_AT_TOP
			float scale = -1.0;
			#else
			loat scale = 1.0;
			#endif
			//o.vertex = UnityObjectToClipPos(v.vertex);
			o.texuv.xy = (float2(o.pos.x, o.pos.y * scale) + o.pos.w) * 0.5;
			o.texuv.zw = o.pos.zw;
			//o.texuv = v.texcoord;
			return o;
		}
		
		v2f vertBlurHorizontal(appdata v) {
			//v2f o;
			//o.pos = UnityObjectToClipPos(v.vertex);
			//o.texuv = v.texcoord;		 
			//return o;

						v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			#if UNITY_UV_STARTS_AT_TOP
			float scale = -1.0;
			#else
			loat scale = 1.0;
			#endif
			//o.vertex = UnityObjectToClipPos(v.vertex);
			o.texuv.xy = (float2(o.pos.x, o.pos.y * scale) + o.pos.w) * 0.5;
			o.texuv.zw = o.pos.zw;
			//o.texuv = v.texcoord;
			return o;
		}
		
		float4 GetGaussBlurColor( float2 uv )
		{
			//算出一个像素的空间
			float space = 1.0/_TextureSize; 
			//参考正态分布曲线图,可以知道 3σ 距离以外的点,权重已经微不足道了。
			//反推即可知道当模糊半径为r时,取σ为 r/3 是一个比较合适的取值。
			float rho = (float)_BlurRadius * space / 3.0;

			//---权重总和
			float weightTotal = _BlurRadius * _BlurRadius * 2 * _Weight;
			//--------
			float4 colorTmp = float4(0,0,0,0);
			float weight = _Weight/weightTotal;
			float blurdadius = _BlurRadius/1.5;
			for( int x = -blurdadius ; x <= blurdadius ; x++ )
			{
				for( int y = -blurdadius ; y <= blurdadius ; y++ )
				{
					float4 color = tex2D(_MainTex,uv + float2(x * _TextureSize,y * _TextureSize));
					color = color * weight;
					colorTmp += color;
				}
			}
			return colorTmp;
		}

		fixed4 fragBlur(v2f i) : SV_Target {
			return GetGaussBlurColor(i.texuv);
		}
		    
		ENDCG
		
		ZTest Always Cull Off ZWrite Off
		
		Pass {
			NAME "GAUSSIAN_BLUR_VERTICAL"
			
			CGPROGRAM
			  
			#pragma vertex vertBlurVertical  
			#pragma fragment fragBlur
			  
			ENDCG  
		}
		
		Pass {  
			NAME "GAUSSIAN_BLUR_HORIZONTAL"
			
			CGPROGRAM  
			
			#pragma vertex vertBlurHorizontal  
			#pragma fragment fragBlur
			
			ENDCG
		}
	} 
	FallBack "Diffuse"
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值