挂在摄像机上的脚本,把source抄到中间临时纹理,然后再到destination
由于用到HDR,camera打开Allow HDR
void OnRenderImage (RenderTexture source, RenderTexture destination) {
RenderTexture r = RenderTexture.GetTemporary(
source.width, source.height, 0, source.format
);
Graphics.Blit(source, r);
Graphics.Blit(r, destination);
RenderTexture.ReleaseTemporary(r);
}
Blur:利用GPU内置的双线性过滤,最为简单并且运行效率最高。通过改变临时纹理分辨率为一半(除以2)downsampling,在回到destination,upsampling即可。
这样可以除以2、4、8、16、32……用更小分辨率的中间纹理得到更模糊的图像,但是效果不佳。
为提高效果,要渐进处理不要直接使用source直接blit到小分辨率中间纹理上。
[Range(1, 16)]
public int iterations = 4;
RenderTexture[] textures = new RenderTexture[16];
void OnRenderImage (RenderTexture source, RenderTexture destination) {
int width = source.width / 2;
int height = source.height / 2;
RenderTextureFormat format = source.format;
RenderTexture currentDestination = textures[0] =
RenderTexture.GetTemporary(width, height, 0, format);
Graphics.Blit(source, currentDestination);
RenderTexture currentSource = currentDestination;
int i = 1;
for (; i < iterations; i++) {
width /= 2;
height /= 2;
if (height < 2) {
break;
}
currentDestination = textures[i] =
RenderTexture.GetTemporary(width, height, 0, format);
Graphics.Blit(currentSource, currentDestination);
currentSource = currentDestination;
}
for (i -= 2; i >= 0; i--) {
currentDestination = textures[i];
textures[i] = null;
Graphics.Blit(currentSource, currentDestination);
RenderTexture.ReleaseTemporary(currentSource);
currentSource = currentDestination;
}
Graphics.Blit(currentSource, destination);
RenderTexture.ReleaseTemporary(currentSource);
}
改善GPU双线性的效果
要用自己box filter kernel代替GPU的采样,要使用自己的shader
Shader "Custom/Bloom" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_TexelSize;
struct VertexData {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct Interpolators {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
// vs没有特别用处,ps定义在不同的pass里
Interpolators VertexProgram (VertexData v) {
Interpolators i;
i.pos = UnityObjectToClipPos(v.vertex);
i.uv = v.uv;
return i;
}
// 采样,只是rgb
half3 Sample (float2 uv) {
return tex2D(_MainTex, uv).rgb;
}
// box 采样,通过delta来决定是up还是down
half3 SampleBox (float2 uv, float delta) {
float4 o = _MainTex_TexelSize.xyxy * fl