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