• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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