shader实现屏幕Bloom效果

   首先,bloom的实现原理:先根据阈值提取中图像中较亮的区域,把他们存储在一张渲染纹理中,再利用高斯模糊对这张渲染纹理进行模糊处理,模拟光线扩散的效果,最后和原图像进行混合,得到最终效果。

接下来就上代码:

1.新建一个C#脚本,屏幕处理的预处理

[ExecuteInEditMode]

[RequireComponent (typeof(Camera))]

public class PostEffectsBase : MonoBehaviour {

protected void CheckResources() {

bool isSupported = CheckSupport();

if (isSupported == false) {

NotSupported();

}

}

protected bool CheckSupport() {

if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false) {

Debug.LogWarning("This platform does not support image effects or render textures.");

return false;

}

return true;

}

protected void NotSupported() {

enabled = false;

}

protected void Start() {

CheckResources();

}

protected Material CheckShaderAndCreateMaterial(Shader shader, Material material) {

if (shader == null) {

return null;

}

if (shader.isSupported && material && material.shader == shader)

return material;

if (!shader.isSupported) {

return null;

}

else {

material = new Material(shader);

material.hideFlags = HideFlags.DontSave;

if (material)

return material;

else

return null;

}}}

2.再建一个c#脚本,继承自上面的PostEffectsBase基类,且该脚本必须挂在摄像机上

public class Bloom : PostEffectsBase {

public Shader bloomShader;

private Material bloomMaterial = null;

public Material material {

get {

bloomMaterial = CheckShaderAndCreateMaterial(bloomShader, bloomMaterial);

return bloomMaterial;

}

}

[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;

[Range(0.0f, 4.0f)]

public float luminanceThreshold = 0.6f;

void OnRenderImage (RenderTexture src, RenderTexture dest) {

if (material != null) {

material.SetFloat("_LuminanceThreshold", luminanceThreshold);

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, material, 0);

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

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

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

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

RenderTexture.ReleaseTemporary(buffer0);

buffer0 = buffer1;

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

// Render the horizontal pass

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

RenderTexture.ReleaseTemporary(buffer0);

buffer0 = buffer1;

}

material.SetTexture ("_Bloom", buffer0);

Graphics.Blit (src, dest, material, 3);

RenderTexture.ReleaseTemporary(buffer0);

} else {

Graphics.Blit(src, dest);

}

}

}

3.新建一个屏幕Bloom效果的shader

Shader "Unity Shaders Book/Chapter 12/Bloom" {

Properties {

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

_Bloom ("Bloom (RGB)", 2D) = "black" {}

_LuminanceThreshold ("Luminance Threshold", Float) = 0.5

_BlurSize ("Blur Size", Float) = 1.0

}

SubShader {

CGINCLUDE

#include "UnityCG.cginc"

sampler2D _MainTex;

half4 _MainTex_TexelSize;

sampler2D _Bloom;

float _LuminanceThreshold;

float _BlurSize;

struct v2f {

float4 pos : SV_POSITION;

half2 uv : TEXCOORD0;

};

v2f vertExtractBright(appdata_img v) {

v2f o;

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

o.uv = v.texcoord;

return o;

}

fixed luminance(fixed4 color) {

return  0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;

}

fixed4 fragExtractBright(v2f i) : SV_Target {

fixed4 c = tex2D(_MainTex, i.uv);

fixed val = clamp(luminance(c) - _LuminanceThreshold, 0.0, 1.0);//亮度值再乘颜色

return c * val;

}

struct v2fBloom {

float4 pos : SV_POSITION;

half4 uv : TEXCOORD0;

};

v2fBloom vertBloom(appdata_img v) {

v2fBloom o;

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

o.uv.xy = v.texcoord;

o.uv.zw = v.texcoord;

#if UNITY_UV_STARTS_AT_TOP

if (_MainTex_TexelSize.y < 0.0)

o.uv.w = 1.0 - o.uv.w;

#endif

return o;

}

fixed4 fragBloom(v2fBloom i) : SV_Target {

return tex2D(_MainTex, i.uv.xy) + tex2D(_Bloom, i.uv.zw);

}

ENDCG

ZTest Always Cull Off ZWrite Off

Pass {

CGPROGRAM

#pragma vertex vertExtractBright

#pragma fragment fragExtractBright

ENDCG

}

UsePass "Unity Shaders Book/Chapter 12/Gaussian Blur/GAUSSIAN_BLUR_VERTICAL"

UsePass "Unity Shaders Book/Chapter 12/Gaussian Blur/GAUSSIAN_BLUR_HORIZONTAL"

Pass {

CGPROGRAM

#pragma vertex vertBloom

#pragma fragment fragBloom

ENDCG

}

}

FallBack Off

}

注:下载一张贴图到导入unity中,把属性改为Sprite,然后拉入场景中,是之充满整个屏幕。

实现效果图:


shader实现屏幕Bloom效果_第1张图片

你可能感兴趣的:(shader实现屏幕Bloom效果)