完成图前置
我在UE中实现的bloom
Bloom
1.降采样与提取亮度
原始分辨率为2448×1368,降采样至344×192的同时根据阈值参数拿到发光颜色。
根据四个方向偏移一像素采样四次,求和平均(降采样),然后减去一个用户阈值
//降采样 float4 a = tex.Sample(linear, offsetA); float4 b = tex.Sample(linear, offsetB); float4 c = tex.Sample(linear, offsetC); float4 d = tex.Sample(linear, offsetD); float color = (a + b + c + d) * 0.25; //减去用户参数-阈值 color.rgb = max(color.rgb - Threshould;, 0) * Intensity; return color;
这里的Threshould为0.44922
2 在344×192上做横纵两次模糊
模糊shader为:MultipleGaussPassFilter
分别采样六次,并乘以一个系数后相加,六个系数相加后正好为一,应该就是卷积核:
float4 a = t.Sample(s, User * -2.2226281 + uv) * 0.1334844; float4 b = t.Sample(s, User * -4.0952849 + uv) * 0.0057047; float4 c = t.Sample(s, User * -0.437803 + uv) * 0.501892; float4 d = t.Sample(s, User * 1.320767 + uv) * 0.3234969; float4 e = t.Sample(s, User * 3.147974 + uv) * 0.0348785; float4 f = t.Sample(s, User * 5 + uv) * 0.0005436; return a + b + c + d + e + f;
第一次横向模糊的User值为(0.0029, 0),这个值正好为纹理宽度的倒数(1/344),代表一像素。在代码中的User * -2.2226281偏移量就是就是按像素偏移。
用第一次横向模糊的结果在进行第二次纵向模糊,User值为(0. 0.0052),同样是高度(192)的一像素
3 多次降采样与模糊
将344×192降采样三次至153×161纹理的大小,应该是为了节省RT申请和切换。要先在同一张RT上算完三张图的横向模糊,在切换RT计算纵向模糊。
- Pass0
- 降采样大图
- 降采样中图
- 降采样小图
- Pass1
- 横向模糊大图
- 横向模糊中图
- 横向模糊小图
- Pass2
- 纵向模糊大图
- 纵向模糊中图
- 纵向模糊小图
降采样算法同上一次降采样一致,采样四次后平均。
但两次模糊算法的采样次数和卷积核有所不同。并且分辨率越低,模糊采样次数越多,扩散范围越大(卷积核越大)。
大图模糊的9次采样
float a = t.Sample(s, uv + User * -5.2274981) * 0.0151298; float b = t.Sample(s, uv + User * -7.1588202) * 0.0009649; float c = t.Sample(s, uv + User * -3.3147621) * 0.1009583; float d = t.Sample(s, uv + User * -1.417412) * 0.2889; float e = t.Sample(s, uv + User * 0.4722446) * 0.3564036; float f = t.Sample(s, uv + User * 2.364548) * 0.1897708; float g = t.Sample(s, uv + User * 4.268898) * 0.0434656; float h = t.Sample(s, uv + User * 6.1908078) * 0.0042536; float i = t.Sample(s, uv + User * 8) * 0.0001532; return a + b + c + d + e + f + g + h + i;
横向模糊User为(0.00653, 0),纵向模糊User为(0, 0.00616)
中图的16次采样
float4 blur = 0; blur += t.Sample(s, uv + User * -12.2933798) * 0.0009471; blur += t.Sample(s, uv + User * -14.26509) * 0.0001463; blur += t.Sample(s, uv + User * -10.3233604) * 0.0046463; blur += t.Sample(s, uv + User * -8.3548632) * 0.0172796; blur += t.Sample(s, uv + User * -6.3876772) * 0.0487266; blur += t.Sample(s, uv + User * -4.4215422) * 0.1042022; blur += t.Sample(s, uv + User * -2.456162) * 0.1690129; blur += t.Sample(s, uv + User * -0.4912108) * 0.207937; blur += t.Sample(s, uv + User * 1.473654) * 0.1940565; blur += t.Sample(s, uv + User * 3.4387779) * 0.1373738; blur += t.Sample(s, uv + User * 5.4044962) * 0.0737621; blur += t.Sample(s, uv + User * 7.3711209) * 0.0300379; blur += t.Sample(s, uv + User * 9.338933) * 0.0092757; blur += t.Sample(s, uv + User * 11.3081703) * 0.0021717; blur += t.Sample(s, uv + User * 13.2790203) * 0.0003854; blur += t.Sample(s, uv + User * 15) * 3.8788519e-005; return blur;
横向模糊User为(0.00653, 0),纵向模糊User为(0, 0.00616)
小图的20次采样
float4 blur = 0; blur += t.Sample(s, uv + User * -16.3224392) * 0.0003934; blur += t.Sample(s, uv + User * -18.3031006) * 8.2805367e-005; blur += t.Sample(s, uv + User * -14.3424101) * 0.0015638; blur += t.Sample(s, uv + User * -12.3629599) * 0.0052015; blur += t.Sample(s, uv + User * -10.3840103) * 0.0144784; blur += t.Sample(s, uv + User * -8.4055147) * 0.033726; blur += t.Sample(s, uv + User * -6.4273849) * 0.0657471; blur += t.Sample(s, uv + User * -4.449542) * 0.1072673; blur += t.Sample(s, uv + User * -2.4719019) * 0.1464697; blur += t.Sample(s, uv + User * -0.4943747) * 0.1673879; blur += t.Sample(s, uv + User * 1.48313) * 0.1601027; blur += t.Sample(s, uv + User * 3.4607019) * 0.1281654; blur += t.Sample(s, uv + User * 5.4384332) * 0.0858689; blur += t.Sample(s, uv + User * 7.416409) * 0.0481489; blur += t.Sample(s, uv + User * 9.3947134) * 0.0225949; blur += t.Sample(s, uv + User * 11.3734198) * 0.0088735; blur += t.Sample(s, uv + User * 13.3526201) * 0.0029162; blur += t.Sample(s, uv + User * 15.3323498) * 0.000802; blur += t.Sample(s, uv + User * 17.3126907) * 0.0001846; blur += t.Sample(s, uv + User * 19) * 2.509824e-005;
横向模糊User为(0.00653, 0),纵向模糊User为(0, 0.00616)
将以上四张图使用的卷积核做成数组,可以用循环来采样
static const float2 CORE0[6] = {
float2(-2.2226281, 0.1334844),
float2(-4.0952849, 0.0057047),
float2(-0.437803, 0.501892),
float2(1.320767, 0.3234969),
float2(3.147974, 0.0348785),
float2(5, 0.0005436),
};
static const float2 CORE1[9] = {
float2(-5.2274981, 0.0151298),
float2(-7.1588202, 0.0009649),
float2(-3.3147621, 0.1009583),
float2(-1.417412, 0.2889),
float2(0.4722446, 0.3564036),
float2(2.364548, 0.1897708),
float2(4.268898, 0.0434656),
float2(6.1908078, 0.0042536),
float2(8, 0.0001532),
};
static const float2 CORE2[16] = {
float2(-12.2933798, 0.0009471),
float2(-14.26509, 0.0001463),
float2(-10.3233604, 0.0046463),
float2(-8.3548632, 0.0172796),
float2(-6.3876772, 0.0487266),
float2(-4.4215422, 0.1042022),
float2(-2.456162, 0.1690129),
float2(-0.4912108, 0.207937),
float2(1.473654, 0.1940565),
float2(3.4387779, 0.1373738),
float2(5.4044962, 0.0737621),
float2(7.3711209, 0.0300379),
float2(9.338933, 0.0092757),
float2(11.3081703, 0.0021717),
float2(13.2790203, 0.0003854),
float2(15, 3.8788519e-005),
};
static const float2 CORE3[20] = {
float2(-16.3224392, 0.0003934),
float2(-18.3031006, 8.2805367e-005),
float2(-14.3424101, 0.0015638),
float2(-12.3629599, 0.0052015),
float2(-10.3840103, 0.0144784),
float2(-8.4055147, 0.033726),
float2(-6.4273849, 0.0657471),
float2(-4.449542, 0.1072673),
float2(-2.4719019, 0.1464697),
float2(-0.4943747, 0.1673879),
float2(1.48313, 0.1601027),
float2(3.4607019, 0.1281654),
float2(5.4384332, 0.0858689),
float2(7.416409, 0.0481489),
float2(9.3947134, 0.0225949),
float2(11.3734198, 0.0088735),
float2(13.3526201, 0.0029162),
float2(15.3323498, 0.000802),
float2(17.3126907, 0.0001846),
float2(19, 2.509824e-005),
};
4 四层bloom合并
合并就是把四张图乘以四个用户的强度系数后给加起来,系数的结果正好为1:
- 第0张系数:0.29688
- 第1张系数:0.29688
- 第2张系数:0.25781
- 第3张系数:0.14844
5 合并回原图像
过亮抑制,计算出bloom部分
const float threshold = 0.3; float3 bloomSup = pow(abs(bloomTex.rgb) / threshold, 1.0/3.0) - (1-threshold); float3 bloom = lerp(bloomTex.rgb, bloomSup , bloomTex.rgb >= threshold); bloom *= Intensity;
其中Intensity参数为用户亮度系数,值为1.3
然后加起来获得最终输出
out.rgb = bloom + orignal.rgb; out.a = orignal.a + (bloom.r + bloom.g + bloom.b) * 0.3333;





