美文网首页Unity技术分享
shader实现屏幕高斯模糊

shader实现屏幕高斯模糊

作者: 陈_筱英 | 来源:发表于2017-11-23 18:52 被阅读17次

     实现屏幕模糊的方法有很多种,有均值模糊,中值模糊和高斯模糊。相信了解 过图像处理的对这些都会有一定的了解。这篇文章要实现屏幕的高斯模糊效果。

       讲起来可能有点复杂,还是上代码吧。

1.新建一个C#脚本,改脚本必须挂在摄像机上,同事也是继承自PostEffectsBase(上面一篇文章有,就不再上代码了)

public class GaussianBlur : PostEffectsBase {

public Shader gaussianBlurShader;

private Material gaussianBlurMaterial = null;

public Material material {

get {

gaussianBlurMaterial = CheckShaderAndCreateMaterial(gaussianBlurShader, gaussianBlurMaterial);

return gaussianBlurMaterial;

}

}

// Blur iterations - larger number means more blur.

[Range(0, 4)]

public int iterations = 3;

// Blur spread for each iteration - larger value means more blur

[Range(0.2f, 3.0f)]

public float blurSpread = 0.6f;

[Range(1, 8)]

public int downSample = 2;

void OnRenderImage (RenderTexture src, RenderTexture dest) {

if (material != null) {

int rtW = src.width/downSample;

int rtH = src.height/downSample;

RenderTexture buffer0 = RenderTexture.GetTemporary(rtW, rtH, 0);

buffer0.filterMode = FilterMode.Bilinear;

Graphics.Blit(src, buffer0);

for (int i = 0; i < iterations; i++) {

material.SetFloat("_BlurSize", 1.0f + i * blurSpread);

RenderTexture buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);

// Render the vertical pass

Graphics.Blit(buffer0, buffer1, material, 0);

RenderTexture.ReleaseTemporary(buffer0);

buffer0 = buffer1;

buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);

// Render the horizontal pass

Graphics.Blit(buffer0, buffer1, material, 1);

RenderTexture.ReleaseTemporary(buffer0);

buffer0 = buffer1;

}

Graphics.Blit(buffer0, dest);

RenderTexture.ReleaseTemporary(buffer0);

} else {

Graphics.Blit(src, dest);

}}}

2.新建一个顶点着色器的shader,实现高斯模糊的shader代码如下:

Shader "Unity Shaders Book/Chapter 12/Gaussian Blur" {

Properties {

_MainTex ("Base (RGB)", 2D) = "white" {}

_BlurSize ("Blur Size", Float) = 1.0

}

SubShader {

CGINCLUDE

#include "UnityCG.cginc"

sampler2D _MainTex;

half4 _MainTex_TexelSize;

float _BlurSize;

struct v2f {

float4 pos : SV_POSITION;

half2 uv[5]: TEXCOORD0;

};

v2f vertBlurVertical(appdata_img v) {

v2f o;

o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

half2 uv = v.texcoord;

o.uv[0] = uv;

o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;

o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;

o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;

o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;

return o;

}

v2f vertBlurHorizontal(appdata_img v) {

v2f o;

o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

half2 uv = v.texcoord;

o.uv[0] = uv;

o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;

o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;

o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;

o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;

return o;

}

fixed4 fragBlur(v2f i) : SV_Target {

float weight[3] = {0.4026, 0.2442, 0.0545};

fixed3 sum = tex2D(_MainTex, i.uv[0]).rgb * weight[0];

for (int it = 1; it < 3; it++) {

sum += tex2D(_MainTex, i.uv[it*2-1]).rgb * weight[it];

sum += tex2D(_MainTex, i.uv[it*2]).rgb * weight[it];

}

return fixed4(sum, 1.0);

}

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"

}

注:还是一样的,直接拖一张texture到场景中,但texture的格式要改为Sprite。

最后实现效果:

相关文章

网友评论

    本文标题:shader实现屏幕高斯模糊

    本文链接:https://www.haomeiwen.com/subject/wiqtbxtx.html