1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef SHADERS__COMMON__BLOOM_COMMON_H
17 #define SHADERS__COMMON__BLOOM_COMMON_H
18
19 #include "render/shaders/common/render_color_conversion_common.h"
20 #include "render/shaders/common/render_compatibility_common.h"
21 #include "render/shaders/common/render_post_process_structs_common.h"
22
23 #define CORE_BLOOM_CLAMP_MAX_VALUE 64512.0
24
25 #define CORE_BLOOM_QUALITY_LOW 1
26 #define CORE_BLOOM_QUALITY_NORMAL 2
27 #define CORE_BLOOM_QUALITY_HIGH 4
28
29 #define CORE_BLOOM_TYPE_NORMAL 0.0f
30 #define CORE_BLOOM_TYPE_HORIZONTAL 1.0f
31 #define CORE_BLOOM_TYPE_VERTICAL 2.0f
32
33 /*
34 Combines bloom color with the given base color.
35 */
BloomCombine(vec3 baseColor,vec3 bloomColor,vec4 bloomParameters)36 vec3 BloomCombine(vec3 baseColor, vec3 bloomColor, vec4 bloomParameters)
37 {
38 return baseColor + bloomColor * bloomParameters.z;
39 }
40
41 #define CORE_ENABLE_HEAVY_SAMPLES 1
42
43 /*
44 * Downscales samples.
45 * "Firefly" filter with weighting.
46 */
BloomDownscaleWeighted9(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)47 vec3 BloomDownscaleWeighted9(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
48 {
49 vec3 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(-0.96875, 0.96875) * invTexSize, 0).xyz;
50 float weight = 1.0 / (1.0 + CalcLuma(colSample));
51 vec3 color = colSample * (8.0 / 128.0) * weight;
52 float fullWeight = weight;
53
54 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(0.00000, 0.93750) * invTexSize, 0).xyz;
55 weight = 1.0 / (1.0 + CalcLuma(colSample));
56 color += colSample * (16.0 / 128.0) * weight;
57 fullWeight += weight;
58
59 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(0.96875, 0.96875) * invTexSize, 0).xyz;
60 weight = 1.0 / (1.0 + CalcLuma(colSample));
61 color += colSample * (8.0 / 128.0) * weight;
62 fullWeight += weight;
63
64 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(-0.93750, 0.00000) * invTexSize, 0).xyz;
65 weight = 1.0 / (1.0 + CalcLuma(colSample));
66 color += colSample * (16.0 / 128.0) * weight;
67 fullWeight += weight;
68
69 colSample = textureLod(sampler2D(tex, sampl), uv, 0).xyz;
70 weight = 1.0 / (1.0 + CalcLuma(colSample));
71 color += colSample * (32.0 / 128.0) * weight;
72 fullWeight += weight;
73
74 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(0.93750, 0.00000) * invTexSize, 0).xyz;
75 weight = 1.0 / (1.0 + CalcLuma(colSample));
76 color += colSample * (16.0 / 128.0) * weight;
77 fullWeight += weight;
78
79 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(-0.96875, -0.96875) * invTexSize, 0).xyz;
80 weight = 1.0 / (1.0 + CalcLuma(colSample));
81 color += colSample * (8.0 / 128.0) * weight;
82 fullWeight += weight;
83
84 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(0.00000, -0.93750) * invTexSize, 0).xyz;
85 weight = 1.0 / (1.0 + CalcLuma(colSample));
86 color += colSample * (16.0 / 128.0) * weight;
87 fullWeight += weight;
88
89 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(0.96875, -0.96875) * invTexSize, 0).xyz;
90 weight = 1.0 / (1.0 + CalcLuma(colSample));
91 color += colSample * (8.0 / 128.0) * weight;
92 fullWeight += weight;
93
94 // NOTE: the original bloom has weights
95 // 4 x 0.125
96 // 4 x 025
97 // 5 x 0.5
98 // which results to 4.0 coefficient
99 // here is an approximation coefficient to get a similar bloom value
100 color *= 10.5 / (fullWeight);
101
102 return color;
103 }
104
BloomDownscale9(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)105 vec3 BloomDownscale9(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
106 {
107 vec3 color = textureLod(sampler2D(tex, sampl), uv + vec2(-invTexSize.x, invTexSize.y), 0).rgb * (8.0 / 128.0);
108 color += textureLod(sampler2D(tex, sampl), uv + vec2(0.0, invTexSize.y), 0).rgb * (16.0 / 128.0);
109 color += textureLod(sampler2D(tex, sampl), uv + invTexSize, 0).rgb * (8.0 / 128.0);
110 color += textureLod(sampler2D(tex, sampl), uv + vec2(-invTexSize.x, 0.0), 0).rgb * (16.0 / 128.0);
111 color += textureLod(sampler2D(tex, sampl), uv, 0).rgb * (32.0 / 128.0);
112 color += textureLod(sampler2D(tex, sampl), uv + vec2(invTexSize.x, 0.0), 0).rgb * (16.0 / 128.0);
113 color += textureLod(sampler2D(tex, sampl), uv - invTexSize, 0).rgb * (8.0 / 128.0);
114 color += textureLod(sampler2D(tex, sampl), uv + vec2(0.0, -invTexSize.y), 0).rgb * (16.0 / 128.0);
115 color += textureLod(sampler2D(tex, sampl), uv + vec2(invTexSize.x, -invTexSize.y), 0).rgb * (8.0 / 128.0);
116 return color;
117 }
118
BloomDownScaleHorizontal(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)119 vec3 BloomDownScaleHorizontal(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
120 {
121 vec3 color = textureLod(sampler2D(tex, sampl), uv + vec2(-invTexSize.x * 3, 0.0), 0).rgb * 0.05;
122 color += textureLod(sampler2D(tex, sampl), uv + vec2(-invTexSize.x * 2, 0.0), 0).rgb * 0.10;
123 color += textureLod(sampler2D(tex, sampl), uv + vec2(-invTexSize.x, 0.0), 0).rgb * 0.15;
124 color += textureLod(sampler2D(tex, sampl), uv + vec2(0.0, -invTexSize.y), 0).rgb * 0.05;
125 color += textureLod(sampler2D(tex, sampl), uv, 0).rgb * 0.30;
126 color += textureLod(sampler2D(tex, sampl), uv + vec2(0.0, invTexSize.y), 0).rgb * 0.05;
127 color += textureLod(sampler2D(tex, sampl), uv + vec2(invTexSize.x, 0.0), 0).rgb * 0.15;
128 color += textureLod(sampler2D(tex, sampl), uv + vec2(invTexSize.x * 2, 0.0), 0).rgb * 0.10;
129 color += textureLod(sampler2D(tex, sampl), uv + vec2(invTexSize.x * 3, 0.0), 0).rgb * 0.05;
130 /*
131 // 0.05
132 // Kernel: 0.05 0.10 0.15 0.30 0.15 0.10 0.05
133 // 0.05
134 */
135 return color;
136 }
137
BloomDownScaleVertical(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)138 vec3 BloomDownScaleVertical(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
139 {
140 vec3 color = textureLod(sampler2D(tex, sampl), uv + vec2(0, -invTexSize.y * 3), 0).rgb * 0.05;
141 color += textureLod(sampler2D(tex, sampl), uv + vec2(0, -invTexSize.y * 2), 0).rgb * 0.10;
142 color += textureLod(sampler2D(tex, sampl), uv + vec2(0, -invTexSize.y), 0).rgb * 0.15;
143 color += textureLod(sampler2D(tex, sampl), uv + vec2(-invTexSize.x, 0.0), 0).rgb * 0.05;
144 color += textureLod(sampler2D(tex, sampl), uv, 0).rgb * 0.30;
145 color += textureLod(sampler2D(tex, sampl), uv + vec2(invTexSize.x, 0.0), 0).rgb * 0.05;
146 color += textureLod(sampler2D(tex, sampl), uv + vec2(0, invTexSize.y), 0).rgb * 0.15;
147 color += textureLod(sampler2D(tex, sampl), uv + vec2(0, invTexSize.y * 2), 0).rgb * 0.10;
148 color += textureLod(sampler2D(tex, sampl), uv + vec2(0, invTexSize.y * 3), 0).rgb * 0.05;
149 /*
150 * 0.05
151 * 0.10
152 * 0.15
153 * Kernel: 0.05 0.30 0.05
154 * 0.15
155 * 0.10
156 * 0.05
157 */
158 return color;
159 }
160
BloomSampleAndAdd(in vec2 uv,in float coeff,in texture2D tex,in sampler sampl,inout float fullWeight,inout vec3 fullColor)161 void BloomSampleAndAdd(
162 in vec2 uv, in float coeff, in texture2D tex, in sampler sampl, inout float fullWeight, inout vec3 fullColor)
163 {
164 vec3 colSample = textureLod(sampler2D(tex, sampl), uv, 0).xyz;
165 float weight = 1.0 / (1 + CalcLuma(colSample));
166 fullColor += colSample * coeff * weight;
167 fullWeight += weight;
168 }
169
BloomDownscaleWeighted(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)170 vec3 BloomDownscaleWeighted(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
171 {
172 // first, 9 samples (calculate coefficients)
173 const float diagCoeff = (1.0f / 32.0f);
174 const float stepCoeff = (2.0f / 32.0f);
175 const float centerCoeff = (4.0f / 32.0f);
176
177 const vec2 ts = invTexSize;
178
179 float fullWeight = 0.00001;
180 vec3 color = vec3(0.0);
181 //
182 BloomSampleAndAdd(vec2(uv.x - ts.x, uv.y - ts.y), diagCoeff, tex, sampl, fullWeight, color);
183 BloomSampleAndAdd(vec2(uv.x, uv.y - ts.y), stepCoeff, tex, sampl, fullWeight, color);
184 BloomSampleAndAdd(vec2(uv.x + ts.x, uv.y - ts.y), diagCoeff, tex, sampl, fullWeight, color);
185
186 //
187 BloomSampleAndAdd(vec2(uv.x - ts.x, uv.y), stepCoeff, tex, sampl, fullWeight, color);
188 BloomSampleAndAdd(vec2(uv.x, uv.y), centerCoeff, tex, sampl, fullWeight, color);
189 BloomSampleAndAdd(vec2(uv.x + ts.x, uv.y), stepCoeff, tex, sampl, fullWeight, color);
190
191 //
192 BloomSampleAndAdd(vec2(uv.x - ts.x, uv.y + ts.y), diagCoeff, tex, sampl, fullWeight, color);
193 BloomSampleAndAdd(vec2(uv.x, uv.y + ts.y), centerCoeff, tex, sampl, fullWeight, color);
194 BloomSampleAndAdd(vec2(uv.x + ts.x, uv.y + ts.y), diagCoeff, tex, sampl, fullWeight, color);
195
196 // then center square
197 const vec2 ths = ts * 0.5;
198
199 BloomSampleAndAdd(vec2(uv.x - ths.x, uv.y - ths.y), centerCoeff, tex, sampl, fullWeight, color);
200 BloomSampleAndAdd(vec2(uv.x + ths.x, uv.y - ths.y), centerCoeff, tex, sampl, fullWeight, color);
201 BloomSampleAndAdd(vec2(uv.x - ths.x, uv.y + ths.y), centerCoeff, tex, sampl, fullWeight, color);
202 BloomSampleAndAdd(vec2(uv.x + ths.x, uv.y + ths.y), centerCoeff, tex, sampl, fullWeight, color);
203
204 // NOTE: the original bloom has weights
205 // 4 x 0.125
206 // 4 x 025
207 // 5 x 0.5
208 // which results to 4.0 coefficient
209
210 color *= (13.0 / fullWeight);
211
212 return color;
213 }
214
BloomDownscale(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)215 vec3 BloomDownscale(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
216 {
217 #if (CORE_ENABLE_HEAVY_SAMPLES == 1)
218 // first, 9 samples (calculate coefficients)
219 const float diagCoeff = (1.0f / 32.0f);
220 const float stepCoeff = (2.0f / 32.0f);
221 const float centerCoeff = (4.0f / 32.0f);
222
223 const vec2 ts = invTexSize;
224
225 vec3 color = textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y - ts.y), 0).xyz * diagCoeff;
226 color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y - ts.y), 0).xyz * stepCoeff;
227 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y - ts.y), 0).xyz * diagCoeff;
228
229 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y), 0).xyz * stepCoeff;
230 color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y), 0).xyz * centerCoeff;
231 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y), 0).xyz * stepCoeff;
232
233 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y + ts.y), 0).xyz * diagCoeff;
234 color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y + ts.y), 0).xyz * centerCoeff;
235 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y + ts.y), 0).xyz * diagCoeff;
236
237 // then center square
238 const vec2 ths = ts * 0.5;
239
240 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y - ths.y), 0).xyz * centerCoeff;
241 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0).xyz * centerCoeff;
242 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz * centerCoeff;
243 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y + ths.y), 0).xyz * centerCoeff;
244
245 #else
246
247 const vec2 ths = invTexSize * 0.5;
248
249 // center
250 vec3 color = textureLod(sampler2D(tex, sampl), uv, 0).xyz * 0.5;
251 // corners
252 // 1.0 / 8.0 = 0.125
253 color = textureLod(sampler2D(tex, sampl), uv - ths, 0).xyz * 0.125 + color;
254 color = textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0).xyz * 0.125 + color;
255 color = textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz * 0.125 + color;
256 color = textureLod(sampler2D(tex, sampl), uv + ths, 0).xyz * 0.125 + color;
257
258 #endif
259
260 return color;
261 }
262
263 /*
264 Upscale samples.
265 */
BloomUpscale(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)266 vec3 BloomUpscale(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
267 {
268 const vec2 ts = invTexSize * 2.0;
269
270 // center
271 vec3 color = textureLod(sampler2D(tex, sampl), uv, 0).xyz * (1.0 / 2.0);
272 // corners
273 color = textureLod(sampler2D(tex, sampl), uv - ts, 0).xyz * (1.0 / 8.0) + color;
274 color = textureLod(sampler2D(tex, sampl), uv + vec2(ts.x, -ts.y), 0).xyz * (1.0 / 8.0) + color;
275 color = textureLod(sampler2D(tex, sampl), uv + vec2(-ts.x, ts.y), 0).xyz * (1.0 / 8.0) + color;
276 color = textureLod(sampler2D(tex, sampl), uv + ts, 0).xyz * (1.0 / 8.0) + color;
277
278 return color;
279 }
280
281 /*
282 Upscale horizontally for horizontal bloom
283 */
BloomUpscaleHorizontal(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)284 vec3 BloomUpscaleHorizontal(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
285 {
286 const vec2 ts = invTexSize * 2.0;
287
288 vec3 color = textureLod(sampler2D(tex, sampl), uv + vec2(-ts.x * 3, 0.0), 0).xyz * 0.05;
289 color += textureLod(sampler2D(tex, sampl), uv + vec2(-ts.x * 2, 0.0), 0).xyz * 0.10;
290 color += textureLod(sampler2D(tex, sampl), uv + vec2(-ts.x, 0.0), 0).xyz * 0.15;
291 color += textureLod(sampler2D(tex, sampl), uv + vec2(0.0, -ts.y), 0).xyz * 0.05;
292 color += textureLod(sampler2D(tex, sampl), uv, 0).xyz * 0.30;
293 color += textureLod(sampler2D(tex, sampl), uv + vec2(0.0, ts.y), 0).xyz * 0.05;
294 color += textureLod(sampler2D(tex, sampl), uv + vec2(ts.x, 0.0), 0).xyz * 0.15;
295 color += textureLod(sampler2D(tex, sampl), uv + vec2(ts.x * 2, 0.0), 0).xyz * 0.10;
296 color += textureLod(sampler2D(tex, sampl), uv + vec2(ts.x * 3, 0.0), 0).xyz * 0.05;
297
298 return color;
299 }
300
301 /*
302 Upscale vertically for vertical bloom
303 */
BloomUpscaleVertical(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)304 vec3 BloomUpscaleVertical(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
305 {
306 const vec2 ts = invTexSize * 2.0;
307
308 vec3 color = textureLod(sampler2D(tex, sampl), uv + vec2(0, -ts.y * 3), 0).rgb * 0.05;
309 color += textureLod(sampler2D(tex, sampl), uv + vec2(0, -ts.y * 2), 0).rgb * 0.10;
310 color += textureLod(sampler2D(tex, sampl), uv + vec2(0, -ts.y), 0).rgb * 0.15;
311 color += textureLod(sampler2D(tex, sampl), uv + vec2(-ts.x, 0.0), 0).rgb * 0.05;
312 color += textureLod(sampler2D(tex, sampl), uv, 0).rgb * 0.30;
313 color += textureLod(sampler2D(tex, sampl), uv + vec2(ts.x, 0.0), 0).rgb * 0.05;
314 color += textureLod(sampler2D(tex, sampl), uv + vec2(0, ts.y), 0).rgb * 0.15;
315 color += textureLod(sampler2D(tex, sampl), uv + vec2(0, ts.y * 2), 0).rgb * 0.10;
316 color += textureLod(sampler2D(tex, sampl), uv + vec2(0, ts.y * 3), 0).rgb * 0.05;
317
318 return color;
319 }
320
321 #endif // SHADERS__COMMON__BLOOM_COMMON_H
322