1 /*
2 * Copyright (c) 2024 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_compatibility_common.h"
20 #include "render/shaders/common/render_color_conversion_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 /*
30 Combines bloom color with the given base color.
31 */
bloomCombine(vec3 baseColor,vec3 bloomColor,vec4 bloomParameters)32 vec3 bloomCombine(vec3 baseColor, vec3 bloomColor, vec4 bloomParameters)
33 {
34 return baseColor + bloomColor * bloomParameters.z;
35 }
36
37 #define CORE_ENABLE_HEAVY_SAMPLES 1
38
39 /*
40 * Downscales samples.
41 * "Firefly" filter with weighting.
42 */
bloomDownscaleWeighted9(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)43 vec3 bloomDownscaleWeighted9(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
44 {
45 vec3 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(-0.96875, 0.96875) * invTexSize, 0).xyz;
46 float weight = 1.0 / (1.0 + CalcLuma(colSample));
47 vec3 color = colSample * (8.0 / 128.0) * weight;
48 float fullWeight = weight;
49
50 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(0.00000, 0.93750) * invTexSize, 0).xyz; // 0.00000, 0.93750: param
51 weight = 1.0 / (1.0 + CalcLuma(colSample));
52 color += colSample * (16.0 / 128.0) * weight; // 16.0, 128.0: param
53 fullWeight += weight;
54
55 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(0.96875, 0.96875) * invTexSize, 0).xyz; // 0.96875: param
56 weight = 1.0 / (1.0 + CalcLuma(colSample));
57 color += colSample * (8.0 / 128.0) * weight; // 8.0, 128.0: param
58 fullWeight += weight;
59
60 colSample = textureLod(sampler2D(tex, sampl),
61 uv + vec2(-0.93750, 0.00000) * invTexSize, 0).xyz; // 0.93750, 0.00000:param
62 weight = 1.0 / (1.0 + CalcLuma(colSample));
63 color += colSample * (16.0 / 128.0) * weight; // 16.0, 128.0: param
64 fullWeight += weight;
65
66 colSample = textureLod(sampler2D(tex, sampl), uv, 0).xyz;
67 weight = 1.0 / (1.0 + CalcLuma(colSample));
68 color += colSample * (32.0 / 128.0) * weight; // 32.0, 128.0: param
69 fullWeight += weight;
70
71 colSample = textureLod(sampler2D(tex, sampl),
72 uv + vec2(0.93750, 0.00000) * invTexSize, 0).xyz; // 0.93750, 0.00000:param
73 weight = 1.0 / (1.0 + CalcLuma(colSample));
74 color += colSample * (16.0 / 128.0) * weight; // 16.0, 128.0: param
75 fullWeight += weight;
76
77
78 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(-0.96875, -0.96875) * invTexSize, 0).xyz; // 0.96875:param
79 weight = 1.0 / (1.0 + CalcLuma(colSample));
80 color += colSample * (8.0 / 128.0) * weight; // 8.0, 128.0: param
81 fullWeight += weight;
82
83 colSample = textureLod(sampler2D(tex, sampl),
84 uv + vec2(0.00000, -0.93750) * invTexSize, 0).xyz; // 0.93750, 0.00000:param
85 weight = 1.0 / (1.0 + CalcLuma(colSample));
86 color += colSample * (16.0 / 128.0) * weight; // 16.0, 128.0: param
87 fullWeight += weight;
88
89 colSample = textureLod(sampler2D(tex, sampl), uv + vec2(0.96875, -0.96875) * invTexSize, 0).xyz;// 0.96875:param
90 weight = 1.0 / (1.0 + CalcLuma(colSample));
91 color += colSample * (8.0 / 128.0) * weight; // 8.0, 128.0: param
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); // 10.5: param
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),
109 uv + vec2(0.0, invTexSize.y), 0).rgb * (16.0 / 128.0); // 16.0, 128.0 : param
110 color += textureLod(sampler2D(tex, sampl), uv + invTexSize, 0).rgb * (8.0 / 128.0); // 8.0, 128.0: param
111 color += textureLod(sampler2D(tex, sampl), uv + vec2(-invTexSize.x, 0.0), 0).rgb *
112 (16.0 / 128.0); // 16.0, 128.0: param
113 color += textureLod(sampler2D(tex, sampl), uv, 0).rgb * (32.0 / 128.0); // 32.0, 128.0:param
114 color += textureLod(sampler2D(tex, sampl), uv + vec2(invTexSize.x, 0.0), 0).rgb *
115 (16.0 / 128.0); // 16.0, 128.0:param
116 color += textureLod(sampler2D(tex, sampl), uv - invTexSize, 0).rgb * (8.0 / 128.0); // 8.0, 128.0:param
117 color += textureLod(sampler2D(tex, sampl), uv + vec2(0.0, -invTexSize.y), 0).rgb *
118 (16.0 / 128.0); // 16.0, 128.0: param
119 color += textureLod(sampler2D(tex, sampl), uv +
120 vec2(invTexSize.x, -invTexSize.y), 0).rgb * (8.0 / 128.0);// 8.0,128.0: param
121 return color;
122 }
123
bloomDownscaleWeighted(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)124 vec3 bloomDownscaleWeighted(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
125 {
126 #if (CORE_ENABLE_HEAVY_SAMPLES == 1)
127 // first, 9 samples (calculate coefficients)
128 const float diagCoeff = (1.0f / 32.0f);
129 const float stepCoeff = (2.0f / 32.0f);
130 const float centerCoeff = (4.0f / 32.0f);
131
132 const vec2 ts = invTexSize;
133
134 float fullWeight = 0.00001;
135 //
136 vec3 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y - ts.y), 0).xyz;
137 float weight = 1.0 / (1 + CalcLuma(colSample));
138 vec3 color = colSample * diagCoeff * weight;
139 fullWeight += weight;
140
141 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y - ts.y), 0).xyz;
142 weight = 1.0 / (1 + CalcLuma(colSample));
143 color += colSample * stepCoeff * weight;
144 fullWeight += weight;
145
146 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y - ts.y), 0).xyz;
147 weight = 1.0 / (1 + CalcLuma(colSample));
148 color += colSample * diagCoeff * weight;
149 fullWeight += weight;
150
151 //
152 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y), 0).xyz;
153 weight = 1.0 / (1 + CalcLuma(colSample));
154 color += colSample * stepCoeff * weight;
155 fullWeight += weight;
156
157 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y), 0).xyz;
158 weight = 1.0 / (1 + CalcLuma(colSample));
159 color += colSample * centerCoeff * weight;
160 fullWeight += weight;
161
162 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y), 0).xyz;
163 weight = 1.0 / (1 + CalcLuma(colSample));
164 color += colSample * stepCoeff * weight;
165 fullWeight += weight;
166
167 //
168 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y + ts.y), 0).xyz;
169 weight = 1.0 / (1 + CalcLuma(colSample));
170 color += colSample * diagCoeff * weight;
171 fullWeight += weight;
172
173 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y + ts.y), 0).xyz;
174 weight = 1.0 / (1 + CalcLuma(colSample));
175 color += colSample * centerCoeff * weight;
176 fullWeight += weight;
177
178 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y + ts.y), 0).xyz;
179 weight = 1.0 / (1 + CalcLuma(colSample));
180 color += colSample * diagCoeff * weight;
181 fullWeight += weight;
182
183 // then center square
184 const vec2 ths = ts * 0.5;
185
186 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y - ths.y), 0).xyz;
187 weight = 1.0 / (1 + CalcLuma(colSample));
188 color += colSample * centerCoeff * weight;
189 fullWeight += weight;
190
191 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0).xyz;
192 weight = 1.0 / (1 + CalcLuma(colSample));
193 color += colSample * centerCoeff * weight;
194 fullWeight += weight;
195
196 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz;
197 weight = 1.0 / (1 + CalcLuma(colSample));
198 color += colSample * centerCoeff * weight;
199 fullWeight += weight;
200
201 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y + ths.y), 0).xyz;
202 weight = 1.0 / (1 + CalcLuma(colSample));
203 color += colSample * centerCoeff * weight;
204 fullWeight += weight;
205
206 // NOTE: the original bloom has weights
207 // 4 x 0.125
208 // 4 x 025
209 // 5 x 0.5
210 // which results to 4.0 coefficient
211
212 color *= (13.0 / fullWeight);
213
214 #else
215
216 const vec2 ths = invTexSize * 0.5;
217
218 float fullWeight = 0.00001;
219
220 // center
221 vec3 colSample = textureLod(sampler2D(tex, sampl), uv, 0).xyz;
222 float weight = 1.0 / (1 + CalcLuma(colSample));
223 vec3 color = colSample * 0.5 * weight;
224 fullWeight += weight;
225
226 // corners
227 // 1.0 / 8.0 = 0.125
228 colSample = textureLod(sampler2D(tex, sampl), uv - ths, 0).xyz;
229 weight = 1.0 / (1 + CalcLuma(colSample));
230 color += colSample * 0.125 * weight;
231 fullWeight += weight;
232
233 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0).xyz;
234 weight = 1.0 / (1 + CalcLuma(colSample));
235 color += colSample * 0.125 * weight;
236 fullWeight += weight;
237
238 colSample = textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz;
239 weight = 1.0 / (1 + CalcLuma(colSample));
240 color += colSample * 0.125 * weight;
241 fullWeight += weight;
242
243 colSample = textureLod(sampler2D(tex, sampl), uv + ths, 0).xyz;
244 weight = 1.0 / (1 + CalcLuma(colSample));
245 color += colSample * 0.125 * weight;
246 fullWeight += weight;
247
248 color *= (5.0 / fullWeight);
249 #endif
250
251 return color;
252 }
253
bloomDownscale(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)254 vec3 bloomDownscale(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
255 {
256 #if (CORE_ENABLE_HEAVY_SAMPLES == 1)
257 // first, 9 samples (calculate coefficients)
258 const float diagCoeff = (1.0f / 32.0f);
259 const float stepCoeff = (2.0f / 32.0f);
260 const float centerCoeff = (4.0f / 32.0f);
261
262 const vec2 ts = invTexSize;
263
264 vec3 color = textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y - ts.y), 0).xyz * diagCoeff;
265 color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y - ts.y), 0).xyz * stepCoeff;
266 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y - ts.y), 0).xyz * diagCoeff;
267
268 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y), 0).xyz * stepCoeff;
269 color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y), 0).xyz * centerCoeff;
270 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y), 0).xyz * stepCoeff;
271
272 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y + ts.y), 0).xyz * diagCoeff;
273 color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y + ts.y), 0).xyz * centerCoeff;
274 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y + ts.y), 0).xyz * diagCoeff;
275
276 // then center square
277 const vec2 ths = ts * 0.5;
278
279 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y - ths.y), 0).xyz * centerCoeff;
280 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0).xyz * centerCoeff;
281 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz * centerCoeff;
282 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y + ths.y), 0).xyz * centerCoeff;
283
284 #else
285
286 const vec2 ths = invTexSize * 0.5;
287
288 // center
289 vec3 color = textureLod(sampler2D(tex, sampl), uv, 0).xyz * 0.5;
290 // corners
291 // 1.0 / 8.0 = 0.125
292 color = textureLod(sampler2D(tex, sampl), uv - ths, 0).xyz * 0.125 + color;
293 color = textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0).xyz * 0.125 + color;
294 color = textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz * 0.125 + color;
295 color = textureLod(sampler2D(tex, sampl), uv + ths, 0).xyz * 0.125 + color;
296
297 #endif
298
299 return color;
300 }
301
302 /*
303 Upscale samples.
304 */
bloomUpscale(vec2 uv,vec2 invTexSize,texture2D tex,sampler sampl)305 vec3 bloomUpscale(vec2 uv, vec2 invTexSize, texture2D tex, sampler sampl)
306 {
307 const vec2 ts = invTexSize * 2.0;
308
309 // center
310 vec3 color = textureLod(sampler2D(tex, sampl), uv, 0).xyz * (1.0 / 2.0);
311 // corners
312 color = textureLod(sampler2D(tex, sampl), uv - ts, 0).xyz
313 * (1.0 / 8.0) + color;
314 color = textureLod(sampler2D(tex, sampl), uv + vec2(ts.x, -ts.y), 0).xyz
315 * (1.0 / 8.0) + color;
316 color = textureLod(sampler2D(tex, sampl), uv + vec2(-ts.x, ts.y), 0).xyz
317 * (1.0 / 8.0) + color;
318 color = textureLod(sampler2D(tex, sampl), uv + ts, 0).xyz
319 * (1.0 / 8.0) + color;
320
321 return color;
322 }
323
324 #endif // SHADERS__COMMON__BLOOM_COMMON_H
325