后处理技术(下)

后处理技术(下)

二月 24, 2022

HDRBloom(光晕)

取亮光部分,进行降采样,在升采样的过程中,叠加降采样对应尺寸的图片,合并效果图和源图片

初处理

如果放入的是HDR图片,可以在shader里面加float4 _MainTex_HDR; col.rgb = DecodeHDR(col,_MainTex_HDR);进行解码。

取光亮部分

先进行均值模糊,取亮色部分。

1
2
3
4
5
6
7
float intensity = Mathf.Exp(_Intensity / 10.0f * 0.693f) - 1.0f;

mat.SetFloat("_Threshold", _Threshold);
mat.SetFloat("_Intensity", intensity);

//取亮色
Graphics.Blit(source, RT_Down[0], mat, 0);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
half4 frag_PreFilter(v2f_img i) : SV_Target//0
{
half4 col = tex2D(_MainTex, i.uv);
half4 d=_MainTex_TexelSize.xyxy*half4(1,1,-1,-1);
col.rgb+=tex2D(_MainTex,i.uv+d.xy).rgb;
col.rgb+=tex2D(_MainTex,i.uv+d.zy).rgb;
col.rgb+=tex2D(_MainTex,i.uv+d.xw).rgb;
col.rgb+=tex2D(_MainTex,i.uv+d.zw).rgb;
col.rgb*=0.25;
float br = max(max(col.r,col.g),col.b);
br = max(0,(br - _Threshold))/max(0.00001,br);
col.rgb*=br;
return col;
}

降采样

用双重盒状模糊的降采样方式

1
2
3
4
5
//降采样
for(int i=0;i<_Iteration;i++) {//0-i-1
Graphics.Blit(RT_Down[i], RT_Down[i + 1], mat, 1);
// print("downcode " + i );
}
1
2
3
4
5
6
7
8
9
10
11
half4 frag_DownsampleBox(v2f_img i) : SV_Target//1
{
half4 col = tex2D(_MainTex, i.uv);
half4 d=_MainTex_TexelSize.xyxy*half4(1,1,-1,-1);
col.rgb+=tex2D(_MainTex,i.uv+d.xy).rgb;
col.rgb+=tex2D(_MainTex,i.uv+d.zy).rgb;
col.rgb+=tex2D(_MainTex,i.uv+d.xw).rgb;
col.rgb+=tex2D(_MainTex,i.uv+d.zw).rgb;
col.rgb*=0.25;
return col;
}

升采样

升采样过程中加同尺寸的降采样贴图

1
2
3
4
5
6
7
Graphics.Blit(RT_Down[_Iteration], RT_Up[_Iteration]);
for(int i=_Iteration;i>0;i--) {
mat.SetTexture("_BloomTex", RT_Down[i-1]);
Graphics.Blit(RT_Up[i], RT_Up[i-1], mat, 2);
//print("upcode " + i);

}
1
2
3
4
5
6
7
8
9
10
11
12
half4 frag_UpsampleBox(v2f_img i) : SV_Target//2
{
half4 col = tex2D(_MainTex, i.uv);
half4 d=_MainTex_TexelSize.xyxy*half4(1,1,-1,-1);
col.rgb+=tex2D(_MainTex,i.uv+d.xy).rgb;
col.rgb+=tex2D(_MainTex,i.uv+d.zy).rgb;
col.rgb+=tex2D(_MainTex,i.uv+d.xw).rgb;
col.rgb+=tex2D(_MainTex,i.uv+d.zw).rgb;
col.rgb*=0.25;
half4 color2 = tex2D(_BloomTex, i.uv);
return col + color2;
}

合并

把升采样的最后一张图和原图合并,和释放贴图。

1
2
3
4
5
6
7
8
9
10
mat.SetTexture("_BloomTex", RT_Up[0]);
Graphics.Blit(source, destination, mat, 3);
//Release
//RenderTexture.ReleaseTemporary(RT1);
for (int i = 0; i < _Iteration+1; i++) {
// print("Release " + i);

RenderTexture.ReleaseTemporary(RT_Down[i]);
RenderTexture.ReleaseTemporary(RT_Up[i]);
}
1
2
3
4
5
6
7
half4 frag_Combine(v2f_img i) : SV_Target//3
{
half4 col = tex2D(_MainTex, i.uv);
half3 color1 = tex2D(_BloomTex, i.uv).rgb;
col.rgb+= color1.rgb*_Intensity;
return col ;
}

最后小瑕疵

在光晕的周围还有点不自然。可用如下解决方案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
float3 ACES_Tonemapping(float3 x)
{
float a = 2.51f;
float b = 0.03f;
float c = 2.43f;
float d = 0.59f;
float e = 0.14f;
float3 encode_color = saturate((x*(a*x + b)) / (x*(c*x + d) + e));
return encode_color;
};

half4 frag (v2f_img i) : SV_Target
{
half4 col = tex2D(_MainTex, i.uv);
half3 linear_color = pow(col.rgb, 2.2);
half3 encode_color = ACES_Tonemapping(linear_color);
half3 final_color = pow(encode_color, 1.0 / 2.2);
return float4(final_color,col.a);
}

后处理的顺序

在这里插入图片描述

调整顺序:Bloom->Vignette->Tonemapping->ColorGrading