适用于低性能处理器,没法使用post插件的替代方案,也适用web端;
Shader "Custom/Guassian"
{
Properties {
//定义贴图材质 2D
//_Bloom值 2D
//亮度阙值,float
//模糊尺寸 Float
//辉光强度
_MainTex ("Base (RGB)", 2D) = "white" {}
_Bloom ("Bloom (RGB)", 2D) = "black" {}
_LuminanceThreshold ("Luminance Threshold", Float) = 0.5
_BlurSize ("Blur Size", Float) = 1.0
_BloomPow("辉光强度",Float)=1
_Contrast("对比度",Float)=1
_Brightness("亮度",Float)=1
}
SubShader {
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
half4 _MainTex_TexelSize;
sampler2D _Bloom;
float _LuminanceThreshold;
float _BlurSize;
float _BloomPow,_Contrast,_Saturation,_Brightness,_Temperature,_Tint;
//定义v2f
///pos
///uv
struct v2f {
float4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
};
//提取亮度的顶点着色器,appdata_img
///顶点转换,uv赋值
v2f vertExtractBright(appdata_img v) {
v2f o;
o.pos = UnityObjectToClipPos(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;
}
//提取亮度的片元着色器
///先进行纹理采样
///进行亮度提取,采样得到的亮度值减去阙值,并截取到0-1中
///得到的值和原像素值相乘,得到提取后的亮部区域
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;
}
//白平衡
float3 WhiteBalance(float3 In, float Temperature, float Tint)
{
float t1 = Temperature * 10 / 6;
float t2 = Tint * 10 / 6;
float x = 0.31271 - t1 * (t1 < 0 ? 0.1: 0.05);
float standardIlluminantY = 2.87 * x - 3 * x * x - 0.27509507;
float y = standardIlluminantY + t2 * 0.05;
float3 w1 = float3(0.949237, 1.03542, 1.08728);
float Y = 1;
float X = Y * x / y;
float Z = Y * (1 - x - y) / y;
float L = 0.7328 * X + 0.4296 * Y - 0.1624 * Z;
float M = -0.7036 * X + 1.6975 * Y + 0.0061 * Z;
float S = 0.0030 * X + 0.0136 * Y + 0.9834 * Z;
float3 w2 = float3(L, M, S);
float3 balance = float3(w1.x / w2.x, w1.y / w2.y, w1.z / w2.z);
float3x3 LIN_2_LMS_MAT = {
3.90405e-1, 5.49941e-1, 8.92632e-3,
7.08416e-2, 9.63172e-1, 1.35775e-3,
2.31082e-2, 1.28021e-1, 9.36245e-1
};
float3x3 LMS_2_LIN_MAT = {
2.85847, -1.62879, -2.48910e-2,
- 2.10182e-1, 1.15820, 3.24281e-4,
- 4.18120e-2, -1.18169e-1, 1.06867
};
float3 lms = mul(LIN_2_LMS_MAT, In);
lms *= balance;
float3 Out = mul(LMS_2_LIN_MAT, lms);
return Out;
}
//-----------高斯模糊----------------//
struct v2fGaussian {
float4 pos : SV_POSITION;
half2 uv[5]: TEXCOORD0;
};
v2fGaussian vertBlurVertical(appdata_img v) {
v2fGaussian o;
o.pos = UnityObjectToClipPos(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;
}
v2fGaussian vertBlurHorizontal(appdata_img v) {
v2fGaussian o;
o.pos = UnityObjectToClipPos(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(v2fGaussian 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);
}
///--------混合亮部图像和原图像-----------
///pos和uv,这里的uv是四维xy:_MainTex zw:_Bloom
struct v2fBloom {
float4 pos : SV_POSITION;
half4 uv : TEXCOORD0;
};
//顶点着色器
v2fBloom vertBloom(appdata_img v) {
v2fBloom o;
o.pos = UnityObjectToClipPos (v.vertex);
o.uv.xy = v.texcoord;
o.uv.zw = v.texcoord; //zw是_Bloom,即模糊后的较亮区域的纹理坐标
//平台差异化处理
#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 {
fixed4 TexCol = tex2D(_MainTex, i.uv.xy);
fixed4 BlurCol = tex2D(_Bloom, i.uv.zw)*_BloomPow;
fixed4 Result = TexCol + BlurCol;
//对比度调整
fixed3 avgColor = fixed3(0.5, 0.5, 0.5);
Result.rgb = lerp(avgColor, Result.rgb, _Contrast);
//饱和度调整
fixed luminance = 0.2125 * TexCol.r + 0.7154 * TexCol.g + 0.0721 * TexCol.b;
fixed3 luminanceColor = fixed3(luminance, luminance, luminance);
Result.rgb = lerp(luminanceColor, Result.rgb, _Saturation);
//亮度调整
Result.rgb = Result.rgb * _Brightness;
//白平衡
Result.rgb = WhiteBalance(Result.rgb, _Temperature, _Tint);
return Result;
}
ENDCG
//关闭ZTest ,剔除,深度写入
ZTest Always Cull Off ZWrite Off
Pass {
CGPROGRAM
#pragma vertex vertExtractBright
#pragma fragment fragExtractBright
ENDCG
}
//use pass 的名字会转换成大写字母,使用时要用大写
//usepass in GAUSSIAN_BLUR_VERTICAL
//usepass in GAUSSIAN_BLUR_HORIZONTAL
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
}
Pass {
CGPROGRAM
#pragma vertex vertBloom
#pragma fragment fragBloom
ENDCG
}
}
FallBack Off
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SimpleBloom : BloomPostEffectsBase
{
public Shader GaussianShader;
private Material GaussianMat = null;
// Blur iterations - larger number means more blur.
[Range(0,4)]
public int iterations = 1;
//控制渲染纹理的大小
[Range(1,8)]
public int downSample = 2;
[Range(0.0f, 4.0f)]
public float luminanceThreshold = 0.6f;
[Range(0.2f, 3.0f)]
public float blurSpread = 0.6f;
[Range(0.0f, 3.0f)]
public float BloomPower = 1f;
[Range(0.0f, 3.0f)]
public float Contrast = 1f;
[Range(0.0f, 2.0f)]
public float Saturation = 1f;
[Range(0.0f, 3.0f)]
public float Brightness = 1f;
public float Temperature = 1f;
public float Tint = 1f;
public Material material
{
get
{
GaussianMat = CheckShaderAndCreateMaterial(GaussianShader, GaussianMat);
return GaussianMat;
}
}
protected void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (material != null) {
//设置亮度阙值
material.SetFloat("_LuminanceThreshold", luminanceThreshold);
//定义长宽高
int rtW = source.width / downSample;
int rtH = source.height / downSample;
//定义buffer0缓冲区的大小,设置buffer0的过滤设置,并存储buffer0
RenderTexture buffer0 = RenderTexture.GetTemporary(rtW,rtH,0);
buffer0.filterMode = FilterMode.Bilinear;
Graphics.Blit(source, buffer0, material, 0);
//for循环,iteration次数
for (int i = 0; i < iterations; i++)
{
///for:
///设置blurSize
///新定义RenderTexture buffer1
///Render the vertical pass
///release buffer0
///buffer1赋值给buffer0
///re-define buffer1
///Render the horizontal pass
///释放buffer0
///buffer1赋值给buffer0
material.SetFloat("_BlurSize",1.0f + blurSpread*i);
RenderTexture buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
Graphics.Blit(buffer0,buffer1,material,1);
RenderTexture.ReleaseTemporary(buffer0);
buffer0 = buffer1;
buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
Graphics.Blit(buffer0, buffer1, material, 2);
RenderTexture.ReleaseTemporary(buffer0);
buffer0 = buffer1;
}
//mat中将buffer0赋予给_Bloom
material.SetTexture("_Bloom",buffer0);
//发光强度
material.SetFloat("_BloomPow",BloomPower);
//对比度
material.SetFloat("_Contrast",Contrast);
//饱和度
material.SetFloat("_Saturation",Saturation);
//亮度
material.SetFloat("_Brightness",Brightness);
//
material.SetFloat("_Temperature",Temperature);
material.SetFloat("_Tint",Tint);
//渲染图像到des上
Graphics.Blit(source,destination,material,3);
//释放buffer0
RenderTexture.ReleaseTemporary(buffer0);
}
else
{
Graphics.Blit(source,destination);
}
}
}
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
[RequireComponent (typeof(Camera))]
public class BloomPostEffectsBase : MonoBehaviour
{
/// <summary>
/// 用指定shader生成一个材质
/// </summary>
/// <param name="shader"></param>
/// <param name="material"></param>
/// <returns></returns>
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;
}
}
}