1 /*
2 * Copyright (C) 2023 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 API_RENDER_SHADERS_COMMON_CORE_BLUR_COMMON_H
17 #define API_RENDER_SHADERS_COMMON_CORE_BLUR_COMMON_H
18
19 // includes
20 #include "render_compatibility_common.h"
21
22 // specialization for CORE_BLUR_COLOR_TYPE.
23 // These are defines instead of contants to avoid extra code generation in shaders.
24 #define CORE_BLUR_TYPE_RGBA 0
25 #define CORE_BLUR_TYPE_R 1
26 #define CORE_BLUR_TYPE_RG 2
27 #define CORE_BLUR_TYPE_RGB 3
28 #define CORE_BLUR_TYPE_A 4
29 #define CORE_BLUR_TYPE_SOFT_DOWNSCALE_RGB 5
30 #define CORE_BLUR_TYPE_DOWNSCALE_RGBA 6
31 #define CORE_BLUR_FILTER_SIZE 3
32
33 #ifndef VULKAN
34 #include <render/namespace.h>
35 RENDER_BEGIN_NAMESPACE()
36 #endif
37
38 #ifndef VULKAN
39 RENDER_END_NAMESPACE()
40 #endif
41
42 #ifdef VULKAN
43 /**
44 http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
45 */
46
47 const float CORE_BLUR_OFFSETS[CORE_BLUR_FILTER_SIZE] = { 0.0, 1.3846153846, 3.2307692308 };
48 const float CORE_BLUR_WEIGHTS[CORE_BLUR_FILTER_SIZE] = { 0.2270270270, 0.3162162162, 0.0702702703 };
49
GaussianBlurRGBA(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)50 vec4 GaussianBlurRGBA(
51 texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
52 {
53 vec4 color = textureLod(sampler2D(tex, sampl), uv, 0) * CORE_BLUR_WEIGHTS[0];
54
55 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
56 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
57
58 color +=
59 textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset) * invTexSize, 0) * CORE_BLUR_WEIGHTS[idx];
60 color +=
61 textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset) * invTexSize, 0) * CORE_BLUR_WEIGHTS[idx];
62 }
63
64 return color;
65 }
66
GaussianBlurRGB(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)67 vec3 GaussianBlurRGB(
68 texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
69 {
70 vec3 color = textureLod(sampler2D(tex, sampl), uv, 0).xyz * CORE_BLUR_WEIGHTS[0];
71
72 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
73 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
74
75 color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset) * invTexSize, 0).xyz *
76 CORE_BLUR_WEIGHTS[idx];
77 color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset) * invTexSize, 0).xyz *
78 CORE_BLUR_WEIGHTS[idx];
79 }
80
81 return color;
82 }
83
GaussianBlurRG(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)84 vec2 GaussianBlurRG(
85 texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
86 {
87 vec2 color = textureLod(sampler2D(tex, sampl), uv, 0).xy * CORE_BLUR_WEIGHTS[0];
88
89 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
90 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
91
92 color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset) * invTexSize, 0).xy *
93 CORE_BLUR_WEIGHTS[idx];
94 color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset) * invTexSize, 0).xy *
95 CORE_BLUR_WEIGHTS[idx];
96 }
97
98 return color;
99 }
100
GaussianBlurR(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)101 float GaussianBlurR(
102 texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
103 {
104 float color = textureLod(sampler2D(tex, sampl), uv, 0).x * CORE_BLUR_WEIGHTS[0];
105
106 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
107 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
108
109 color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset) * invTexSize, 0).x *
110 CORE_BLUR_WEIGHTS[idx];
111 color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset) * invTexSize, 0).x *
112 CORE_BLUR_WEIGHTS[idx];
113 }
114
115 return color;
116 }
117
GaussianBlurA(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)118 float GaussianBlurA(
119 texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
120 {
121 float alpha = textureLod(sampler2D(tex, sampl), uv, 0).a * CORE_BLUR_WEIGHTS[0];
122
123 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
124 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
125
126 alpha += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset, 0) * invTexSize, 0).a *
127 CORE_BLUR_WEIGHTS[idx];
128 alpha += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset, 0) * invTexSize, 0).a *
129 CORE_BLUR_WEIGHTS[idx];
130 }
131
132 return alpha;
133 }
134
GaussianBlurRGBALayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)135 vec4 GaussianBlurRGBALayer(
136 texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
137 {
138 vec4 color = textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0) * CORE_BLUR_WEIGHTS[0];
139
140 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
141 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dirLayer.xy;
142
143 color +=
144 textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) + currOffset) * invTexSize, dirLayer.z), 0) *
145 CORE_BLUR_WEIGHTS[idx];
146 color +=
147 textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) - currOffset) * invTexSize, dirLayer.z), 0) *
148 CORE_BLUR_WEIGHTS[idx];
149 }
150
151 return color;
152 }
153
GaussianBlurRGBLayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)154 vec3 GaussianBlurRGBLayer(
155 texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
156 {
157 vec3 color = textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0).xyz * CORE_BLUR_WEIGHTS[0];
158
159 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
160 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dirLayer.xy;
161
162 color +=
163 textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) + currOffset) * invTexSize, dirLayer.z), 0)
164 .xyz *
165 CORE_BLUR_WEIGHTS[idx];
166 color +=
167 textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) - currOffset) * invTexSize, dirLayer.z), 0)
168 .xyz *
169 CORE_BLUR_WEIGHTS[idx];
170 }
171
172 return color;
173 }
174
GaussianBlurRGLayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)175 vec2 GaussianBlurRGLayer(
176 texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
177 {
178 vec2 color = textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0).xy * CORE_BLUR_WEIGHTS[0];
179
180 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
181 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dirLayer.xy;
182
183 color +=
184 textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) + currOffset) * invTexSize, dirLayer.z), 0)
185 .xy *
186 CORE_BLUR_WEIGHTS[idx];
187 color +=
188 textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) - currOffset) * invTexSize, dirLayer.z), 0)
189 .xy *
190 CORE_BLUR_WEIGHTS[idx];
191 }
192
193 return color;
194 }
195
GaussianBlurRLayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)196 float GaussianBlurRLayer(
197 texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
198 {
199 float color = textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0).x * CORE_BLUR_WEIGHTS[0];
200
201 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
202 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dirLayer.xy;
203
204 color +=
205 textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) + currOffset) * invTexSize, dirLayer.z), 0).x *
206 CORE_BLUR_WEIGHTS[idx];
207 color +=
208 textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) - currOffset) * invTexSize, dirLayer.z), 0).x *
209 CORE_BLUR_WEIGHTS[idx];
210 }
211
212 return color;
213 }
214
GaussianBlurALayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)215 float GaussianBlurALayer(
216 texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
217 {
218 float alpha = textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0).a * CORE_BLUR_WEIGHTS[0];
219
220 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
221 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dirLayer.xy;
222
223 alpha +=
224 textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) + currOffset, 0) * invTexSize, dirLayer.z), 0)
225 .a *
226 CORE_BLUR_WEIGHTS[idx];
227 alpha +=
228 textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) - currOffset, 0) * invTexSize, dirLayer.z), 0)
229 .a *
230 CORE_BLUR_WEIGHTS[idx];
231 }
232
233 return alpha;
234 }
235
236 #define CORE_BLUR_SOFT_HEAVY_SAMPLES 0
237 // NOTE: dir not used
SoftDownscaleRGB(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)238 vec3 SoftDownscaleRGB(
239 texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
240 {
241 #if (CORE_BLUR_SOFT_HEAVY_SAMPLES == 1)
242
243 // first, 9 samples (calculate coefficients)
244 const float diagCoeff = (1.0f / 32.0f);
245 const float stepCoeff = (2.0f / 32.0f);
246 const float centerCoeff = (4.0f / 32.0f);
247
248 const vec2 ts = invTexSize;
249
250 vec3 color = textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y - ts.y), 0).xyz * diagCoeff;
251 color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y - ts.y), 0).xyz * stepCoeff;
252 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y - ts.y), 0).xyz * diagCoeff;
253
254 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y), 0).xyz * stepCoeff;
255 color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y), 0).xyz * centerCoeff;
256 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y), 0).xyz * stepCoeff;
257
258 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y + ts.y), 0).xyz * diagCoeff;
259 color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y + ts.y), 0).xyz * centerCoeff;
260 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y + ts.y), 0).xyz * diagCoeff;
261
262 // then center square
263 const vec2 ths = ts * 0.5;
264
265 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y - ths.y), 0).xyz * centerCoeff;
266 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0).xyz * centerCoeff;
267 color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz * centerCoeff;
268 color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y + ths.y), 0).xyz * centerCoeff;
269
270 #else
271
272 const vec2 ths = invTexSize * 0.5;
273
274 // center
275 vec3 color = textureLod(sampler2D(tex, sampl), uv + ths, 0).xyz * 0.5;
276 // corners
277 // 1.0 / 8.0 = 0.125
278 color = textureLod(sampler2D(tex, sampl), uv - ths, 0).xyz * 0.125 + color;
279 color = textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0).xyz * 0.125 + color;
280 color = textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz * 0.125 + color;
281 color = textureLod(sampler2D(tex, sampl), uv + ths, 0).xyz * 0.125 + color;
282
283 #endif
284
285 return color;
286 }
287
DownscaleRGBA(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)288 vec4 DownscaleRGBA(
289 texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
290 {
291 return textureLod(sampler2D(tex, sampl), uv, 0);
292 }
293
SoftDownscaleRGBLayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)294 vec3 SoftDownscaleRGBLayer(
295 texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
296 {
297 #if (CORE_BLUR_SOFT_HEAVY_SAMPLES == 1)
298
299 // first, 9 samples (calculate coefficients)
300 const float diagCoeff = (1.0f / 32.0f);
301 const float stepCoeff = (2.0f / 32.0f);
302 const float centerCoeff = (4.0f / 32.0f);
303
304 const vec2 ts = invTexSize;
305
306 vec3 color = textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ts.x, uv.y - ts.y, dirLayer.z), 0).xyz * diagCoeff;
307 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x, uv.y - ts.y, dirLayer.z), 0).xyz * stepCoeff;
308 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ts.x, uv.y - ts.y, dirLayer.z), 0).xyz * diagCoeff;
309
310 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ts.x, uv.y, dirLayer.z), 0).xyz * stepCoeff;
311 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x, uv.y, dirLayer.z), 0).xyz * centerCoeff;
312 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ts.x, uv.y, dirLayer.z), 0).xyz * stepCoeff;
313
314 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ts.x, uv.y + ts.y, dirLayer.z), 0).xyz * diagCoeff;
315 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x, uv.y + ts.y, dirLayer.z), 0).xyz * centerCoeff;
316 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ts.x, uv.y + ts.y, dirLayer.z), 0).xyz * diagCoeff;
317
318 // then center square
319 const vec2 ths = ts * 0.5;
320
321 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ths.x, uv.y - ths.y, dirLayer.z), 0).xyz * centerCoeff;
322 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ths.x, uv.y - ths.y, dirLayer.z), 0).xyz * centerCoeff;
323 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ths.x, uv.y + ths.y, dirLayer.z), 0).xyz * centerCoeff;
324 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ths.x, uv.y + ths.y, dirLayer.z), 0).xyz * centerCoeff;
325
326 #else
327
328 const vec2 ths = invTexSize * 0.5;
329
330 // center
331 vec3 color = textureLod(sampler2DArray(tex, sampl), vec3(uv + ths, dirLayer.z), 0).xyz * 0.5;
332 // corners
333 // 1.0 / 8.0 = 0.125
334 color = textureLod(sampler2DArray(tex, sampl), vec3(uv - ths, dirLayer.z), 0).xyz * 0.125 + color;
335 color = textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ths.x, uv.y - ths.y, dirLayer.z), 0).xyz * 0.125 + color;
336 color = textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ths.x, uv.y + ths.y, dirLayer.z), 0).xyz * 0.125 + color;
337 color = textureLod(sampler2DArray(tex, sampl), vec3(uv + ths, dirLayer.z), 0).xyz * 0.125 + color;
338
339 #endif
340
341 return color;
342 }
343
DownscaleRGBALayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)344 vec4 DownscaleRGBALayer(
345 texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
346 {
347 return textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0);
348 }
349 #endif
350
351 #endif // API_RENDER_SHADERS_COMMON_CORE_BLUR_COMMON_H
352