• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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_TYPE_DOWNSCALE_RGBA_DOF 7
32 #define CORE_BLUR_TYPE_RGBA_DOF 8
33 #define CORE_BLUR_FILTER_SIZE 3
34 
35 #ifndef VULKAN
36 #include <render/namespace.h>
37 RENDER_BEGIN_NAMESPACE()
38 #endif
39 
40 #ifndef VULKAN
41 RENDER_END_NAMESPACE()
42 #endif
43 
44 #ifdef VULKAN
45 /**
46  http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
47 */
48 
49 const float CORE_BLUR_OFFSETS[CORE_BLUR_FILTER_SIZE] = { 0.0, 1.3846153846, 3.2307692308 };
50 const float CORE_BLUR_WEIGHTS[CORE_BLUR_FILTER_SIZE] = { 0.2270270270, 0.3162162162, 0.0702702703 };
51 
GaussianBlurRGBA(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)52 vec4 GaussianBlurRGBA(
53     texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
54 {
55     vec4 color = textureLod(sampler2D(tex, sampl), uv, 0) * CORE_BLUR_WEIGHTS[0];
56 
57     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
58         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
59 
60         color +=
61             textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset) * invTexSize, 0) * CORE_BLUR_WEIGHTS[idx];
62         color +=
63             textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset) * invTexSize, 0) * CORE_BLUR_WEIGHTS[idx];
64     }
65 
66     return color;
67 }
68 
GaussianBlurRGB(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)69 vec3 GaussianBlurRGB(
70     texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
71 {
72     vec3 color = textureLod(sampler2D(tex, sampl), uv, 0).xyz * CORE_BLUR_WEIGHTS[0];
73 
74     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
75         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
76 
77         color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset) * invTexSize, 0).xyz *
78                  CORE_BLUR_WEIGHTS[idx];
79         color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset) * invTexSize, 0).xyz *
80                  CORE_BLUR_WEIGHTS[idx];
81     }
82 
83     return color;
84 }
85 
GaussianBlurRG(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)86 vec2 GaussianBlurRG(
87     texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
88 {
89     vec2 color = textureLod(sampler2D(tex, sampl), uv, 0).xy * CORE_BLUR_WEIGHTS[0];
90 
91     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
92         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
93 
94         color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset) * invTexSize, 0).xy *
95                  CORE_BLUR_WEIGHTS[idx];
96         color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset) * invTexSize, 0).xy *
97                  CORE_BLUR_WEIGHTS[idx];
98     }
99 
100     return color;
101 }
102 
GaussianBlurR(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)103 float GaussianBlurR(
104     texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
105 {
106     float color = textureLod(sampler2D(tex, sampl), uv, 0).x * CORE_BLUR_WEIGHTS[0];
107 
108     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
109         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
110 
111         color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset) * invTexSize, 0).x *
112                  CORE_BLUR_WEIGHTS[idx];
113         color += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset) * invTexSize, 0).x *
114                  CORE_BLUR_WEIGHTS[idx];
115     }
116 
117     return color;
118 }
119 
GaussianBlurA(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)120 float GaussianBlurA(
121     texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
122 {
123     float alpha = textureLod(sampler2D(tex, sampl), uv, 0).a * CORE_BLUR_WEIGHTS[0];
124 
125     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
126         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
127 
128         alpha += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset, 0) * invTexSize, 0).a *
129                  CORE_BLUR_WEIGHTS[idx];
130         alpha += textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset, 0) * invTexSize, 0).a *
131                  CORE_BLUR_WEIGHTS[idx];
132     }
133 
134     return alpha;
135 }
136 
GaussianBlurRGBALayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)137 vec4 GaussianBlurRGBALayer(
138     texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
139 {
140     vec4 color = textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0) * CORE_BLUR_WEIGHTS[0];
141 
142     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
143         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dirLayer.xy;
144 
145         color +=
146             textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) + currOffset) * invTexSize, dirLayer.z), 0) *
147             CORE_BLUR_WEIGHTS[idx];
148         color +=
149             textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) - currOffset) * invTexSize, dirLayer.z), 0) *
150             CORE_BLUR_WEIGHTS[idx];
151     }
152 
153     return color;
154 }
155 
GaussianBlurRGBLayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)156 vec3 GaussianBlurRGBLayer(
157     texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
158 {
159     vec3 color = textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0).xyz * CORE_BLUR_WEIGHTS[0];
160 
161     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
162         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dirLayer.xy;
163 
164         color +=
165             textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) + currOffset) * invTexSize, dirLayer.z), 0)
166                 .xyz *
167             CORE_BLUR_WEIGHTS[idx];
168         color +=
169             textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) - currOffset) * invTexSize, dirLayer.z), 0)
170                 .xyz *
171             CORE_BLUR_WEIGHTS[idx];
172     }
173 
174     return color;
175 }
176 
GaussianBlurRGLayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)177 vec2 GaussianBlurRGLayer(
178     texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
179 {
180     vec2 color = textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0).xy * CORE_BLUR_WEIGHTS[0];
181 
182     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
183         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dirLayer.xy;
184 
185         color +=
186             textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) + currOffset) * invTexSize, dirLayer.z), 0)
187                 .xy *
188             CORE_BLUR_WEIGHTS[idx];
189         color +=
190             textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) - currOffset) * invTexSize, dirLayer.z), 0)
191                 .xy *
192             CORE_BLUR_WEIGHTS[idx];
193     }
194 
195     return color;
196 }
197 
GaussianBlurRLayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)198 float GaussianBlurRLayer(
199     texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
200 {
201     float color = textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0).x * CORE_BLUR_WEIGHTS[0];
202 
203     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
204         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dirLayer.xy;
205 
206         color +=
207             textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) + currOffset) * invTexSize, dirLayer.z), 0).x *
208             CORE_BLUR_WEIGHTS[idx];
209         color +=
210             textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) - currOffset) * invTexSize, dirLayer.z), 0).x *
211             CORE_BLUR_WEIGHTS[idx];
212     }
213 
214     return color;
215 }
216 
GaussianBlurALayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)217 float GaussianBlurALayer(
218     texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
219 {
220     float alpha = textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0).a * CORE_BLUR_WEIGHTS[0];
221 
222     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
223         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dirLayer.xy;
224 
225         alpha +=
226             textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) + currOffset, 0) * invTexSize, dirLayer.z), 0)
227                 .a *
228             CORE_BLUR_WEIGHTS[idx];
229         alpha +=
230             textureLod(sampler2DArray(tex, sampl), vec3((vec2(fragCoord) - currOffset, 0) * invTexSize, dirLayer.z), 0)
231                 .a *
232             CORE_BLUR_WEIGHTS[idx];
233     }
234 
235     return alpha;
236 }
237 
238 #define CORE_BLUR_SOFT_HEAVY_SAMPLES 0
239 // NOTE: dir not used
SoftDownscaleRGB(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)240 vec3 SoftDownscaleRGB(
241     texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
242 {
243 #if (CORE_BLUR_SOFT_HEAVY_SAMPLES == 1)
244 
245     // first, 9 samples (calculate coefficients)
246     const float diagCoeff = (1.0f / 32.0f); // 32.0 : param
247     const float stepCoeff = (2.0f / 32.0f); // 2.0, 32.0 : param
248     const float centerCoeff = (4.0f / 32.0f); // 4.0, 32.0 : param
249 
250     const vec2 ts = invTexSize;
251 
252     vec3 color = textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y - ts.y), 0).xyz * diagCoeff;
253     color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y - ts.y), 0).xyz * stepCoeff;
254     color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y - ts.y), 0).xyz * diagCoeff;
255 
256     color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y), 0).xyz * stepCoeff;
257     color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y), 0).xyz * centerCoeff;
258     color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y), 0).xyz * stepCoeff;
259 
260     color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ts.x, uv.y + ts.y), 0).xyz * diagCoeff;
261     color += textureLod(sampler2D(tex, sampl), vec2(uv.x, uv.y + ts.y), 0).xyz * centerCoeff;
262     color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ts.x, uv.y + ts.y), 0).xyz * diagCoeff;
263 
264     // then center square
265     const vec2 ths = ts * 0.5; // 0.5 half
266 
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     color += textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz * centerCoeff;
270     color += textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y + ths.y), 0).xyz * centerCoeff;
271 
272 #else
273 
274     const vec2 ths = invTexSize * 0.5; // 0.5 : half
275 
276     // center
277     vec3 color = textureLod(sampler2D(tex, sampl), uv + ths, 0).xyz * 0.5; // 0.5 : half
278     // corners
279     color = textureLod(sampler2D(tex, sampl), uv - ths, 0).xyz * 0.125 + color; // 0.125 : param
280     color = textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0).xyz * 0.125 + color; // 0.125:param
281     color = textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz * 0.125 + color; // 0.125:param
282     color = textureLod(sampler2D(tex, sampl), uv + ths, 0).xyz * 0.125 + color; // 0.125:pram
283 
284 #endif
285 
286     return color;
287 }
288 
DownscaleRGBA(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)289 vec4 DownscaleRGBA(
290     texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
291 {
292     return textureLod(sampler2D(tex, sampl), uv, 0);
293 }
294 
DownscaleRGBADof(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)295 vec4 DownscaleRGBADof(
296     texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
297 {
298     const vec2 ths = invTexSize * 0.5; // 0.5 : half
299 
300     vec4 color = vec4(0);
301 
302     // 1.0 / 8.0 = 0.125
303     float weights[5] = { 0.5, 0.125, 0.125, 0.125, 0.125 }; // 5 :size 0.125 : param
304     vec4 samples[5] = { // 5 : size
305         // center
306         textureLod(sampler2D(tex, sampl), uv, 0),
307         // corners
308         textureLod(sampler2D(tex, sampl), uv - ths, 0),
309         textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0),
310         textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0),
311         textureLod(sampler2D(tex, sampl), uv + ths, 0),
312     };
313     float weight = 0.0;
314     for (int i = 0; i < 5; ++i) { // 5 : size
315         weight += samples[i].a;
316     }
317     if (weight > 0.0) {
318         for (int i = 0; i < 5; ++i) { // 5 : size
319             color += samples[i] * weights[i];
320         }
321     } else {
322         color = samples[0];
323     }
324 
325     return color;
326 }
327 
BlurRGBADof(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)328 vec4 BlurRGBADof(
329     texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
330 {
331     const vec2 ths = invTexSize * 0.5; // 0.5 : half
332 
333     CORE_RELAXEDP vec4 color = vec4(0);
334 
335     CORE_RELAXEDP vec4 samples[1 + 2 * CORE_BLUR_FILTER_SIZE]; // 2 :param
336     samples[0] = textureLod(sampler2D(tex, sampl), uv, 0);
337     float weight = samples[0].a;
338     for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
339         vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
340 
341         samples[idx * 2 - 1] = // 2 : index
342             textureLod(sampler2D(tex, sampl), (vec2(fragCoord) + currOffset) * invTexSize, 0);
343         weight += samples[idx * 2 - 1].a; // 2 : index
344         samples[idx * 2] = textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset) * invTexSize, 0); // 2: idx
345         weight += samples[idx * 2].a; // 2 : idx
346     }
347     if (weight > 0.0) {
348         weight = 1.0 / weight;
349         color = samples[0] * CORE_BLUR_WEIGHTS[0] * weight;
350         for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
351             color += samples[idx * 2 - 1] * CORE_BLUR_WEIGHTS[idx] * weight; // 2 : idx
352             color += samples[idx * 2] * CORE_BLUR_WEIGHTS[idx] * weight; // 2 : idx
353         }
354     } else {
355         color = samples[0];
356     }
357 
358     return color;
359 }
360 
SoftDownscaleRGBLayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)361 vec3 SoftDownscaleRGBLayer(
362     texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
363 {
364 #if (CORE_BLUR_SOFT_HEAVY_SAMPLES == 1)
365 
366     // first, 9 samples (calculate coefficients)
367     const float diagCoeff = (1.0f / 32.0f); // 32.0 : param
368     const float stepCoeff = (2.0f / 32.0f); // 2.0 , 32.0 : param
369     const float centerCoeff = (4.0f / 32.0f); // 4.0, 32.0 : param
370 
371     const vec2 ts = invTexSize;
372 
373     vec3 color = textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ts.x, uv.y - ts.y, dirLayer.z), 0).xyz * diagCoeff;
374     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x, uv.y - ts.y, dirLayer.z), 0).xyz * stepCoeff;
375     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ts.x, uv.y - ts.y, dirLayer.z), 0).xyz * diagCoeff;
376 
377     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ts.x, uv.y, dirLayer.z), 0).xyz * stepCoeff;
378     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x, uv.y, dirLayer.z), 0).xyz * centerCoeff;
379     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ts.x, uv.y, dirLayer.z), 0).xyz * stepCoeff;
380 
381     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ts.x, uv.y + ts.y, dirLayer.z), 0).xyz * diagCoeff;
382     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x, uv.y + ts.y, dirLayer.z), 0).xyz * centerCoeff;
383     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ts.x, uv.y + ts.y, dirLayer.z), 0).xyz * diagCoeff;
384 
385     // then center square
386     const vec2 ths = ts * 0.5; // half
387 
388     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ths.x, uv.y - ths.y, dirLayer.z), 0).xyz * centerCoeff;
389     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ths.x, uv.y - ths.y, dirLayer.z), 0).xyz * centerCoeff;
390     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ths.x, uv.y + ths.y, dirLayer.z), 0).xyz * centerCoeff;
391     color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ths.x, uv.y + ths.y, dirLayer.z), 0).xyz * centerCoeff;
392 
393 #else
394 
395     const vec2 ths = invTexSize * 0.5; // 0.5 : half
396 
397     // center
398     vec3 color = textureLod(sampler2DArray(tex, sampl), vec3(uv + ths, dirLayer.z), 0).xyz * 0.5; // 0.5 : half
399     // corners
400     color = textureLod(sampler2DArray(tex, sampl), vec3(uv - ths, dirLayer.z), 0).xyz * 0.125 + color; // 0.125 : param
401     color = textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ths.x, uv.y - ths.y, dirLayer.z), 0).xyz *
402         0.125 + color; // 0.125 : param
403     color = textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ths.x, uv.y + ths.y, dirLayer.z), 0).xyz *
404         0.125 + color; // 0.125 : param
405     color = textureLod(sampler2DArray(tex, sampl), vec3(uv + ths, dirLayer.z), 0).xyz * 0.125 + color; // 0.125 : param
406 
407 #endif
408 
409     return color;
410 }
411 
DownscaleRGBALayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)412 vec4 DownscaleRGBALayer(
413     texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
414 {
415     return textureLod(sampler2DArray(tex, sampl), vec3(uv, dirLayer.z), 0);
416 }
417 #endif
418 
419 #endif // API_RENDER_SHADERS_COMMON_CORE_BLUR_COMMON_H
420