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);
247 const float stepCoeff = (2.0f / 32.0f);
248 const float centerCoeff = (4.0f / 32.0f);
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;
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;
275
276 // center
277 vec3 color = textureLod(sampler2D(tex, sampl), uv + ths, 0).xyz * 0.5;
278 // corners
279 // 1.0 / 8.0 = 0.125
280 color = textureLod(sampler2D(tex, sampl), uv - ths, 0).xyz * 0.125 + color;
281 color = textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0).xyz * 0.125 + color;
282 color = textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0).xyz * 0.125 + color;
283 color = textureLod(sampler2D(tex, sampl), uv + ths, 0).xyz * 0.125 + color;
284
285 #endif
286
287 return color;
288 }
289
DownscaleRGBA(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)290 vec4 DownscaleRGBA(
291 texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
292 {
293 return textureLod(sampler2D(tex, sampl), uv, 0);
294 }
295
DownscaleRGBADof(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)296 vec4 DownscaleRGBADof(
297 texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
298 {
299 const vec2 ths = invTexSize * 0.5; // 0.5: half
300
301 vec4 color = vec4(0);
302
303 // 1.0 / 8.0 = 0.125
304 float weights[5] = { 0.5, 0.125, 0.125, 0.125, 0.125 }; // 0.5: weight, 0.125: weight
305 vec4 samples[5] = {
306 // center
307 textureLod(sampler2D(tex, sampl), uv, 0),
308 // corners
309 textureLod(sampler2D(tex, sampl), uv - ths, 0),
310 textureLod(sampler2D(tex, sampl), vec2(uv.x + ths.x, uv.y - ths.y), 0),
311 textureLod(sampler2D(tex, sampl), vec2(uv.x - ths.x, uv.y + ths.y), 0),
312 textureLod(sampler2D(tex, sampl), uv + ths, 0),
313 };
314 float weight = 0.0;
315 for (int i = 0; i < 5; ++i) { // 5: size
316 weight += samples[i].a;
317 }
318 if (weight > 0.0) {
319 for (int i = 0; i < 5; ++i) { // 5:size
320 color += samples[i] * weights[i];
321 }
322 } else {
323 color = samples[0];
324 }
325
326 return color;
327 }
328
BlurRGBADof(texture2D tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec2 dir,const vec2 invTexSize)329 vec4 BlurRGBADof(
330 texture2D tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec2 dir, const vec2 invTexSize)
331 {
332 const vec2 ths = invTexSize * 0.5; // 0.5:half
333
334 CORE_RELAXEDP vec4 color = vec4(0);
335
336 CORE_RELAXEDP vec4 samples[1 + 2 * CORE_BLUR_FILTER_SIZE]; // 2: idx
337 samples[0] = textureLod(sampler2D(tex, sampl), uv, 0);
338 float weight = samples[0].a;
339 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
340 vec2 currOffset = vec2(CORE_BLUR_OFFSETS[idx]) * dir.xy;
341
342 samples[idx * 2 - 1] = textureLod(sampler2D(tex, sampl), // 2 : idx
343 (vec2(fragCoord) + currOffset) * invTexSize, 0); // 2: index
344 weight += samples[idx * 2 - 1].a; // 2: size
345 samples[idx * 2] = textureLod(sampler2D(tex, sampl), (vec2(fragCoord) - currOffset) * invTexSize, 0); // 2:idx
346 weight += samples[idx * 2].a; // 2: size
347 }
348 if (weight > 0.0) {
349 weight = 1.0 / weight;
350 color = samples[0] * CORE_BLUR_WEIGHTS[0] * weight;
351 for (int idx = 1; idx < CORE_BLUR_FILTER_SIZE; ++idx) {
352 color += samples[idx * 2 - 1] * CORE_BLUR_WEIGHTS[idx] * weight; // 2: idx
353 color += samples[idx * 2] * CORE_BLUR_WEIGHTS[idx] * weight; // 2 : idex
354 }
355 } else {
356 color = samples[0];
357 }
358
359 return color;
360 }
361
SoftDownscaleRGBLayer(texture2DArray tex,sampler sampl,const vec2 fragCoord,const vec2 uv,const vec3 dirLayer,const vec2 invTexSize)362 vec3 SoftDownscaleRGBLayer(
363 texture2DArray tex, sampler sampl, const vec2 fragCoord, const vec2 uv, const vec3 dirLayer, const vec2 invTexSize)
364 {
365 #if (CORE_BLUR_SOFT_HEAVY_SAMPLES == 1)
366
367 // first, 9 samples (calculate coefficients)
368 const float diagCoeff = (1.0f / 32.0f); // 32.0: param
369 const float stepCoeff = (2.0f / 32.0f); // 2.0: param, 32.0: param
370 const float centerCoeff = (4.0f / 32.0f); //4.0: param, 32.0: param
371
372 const vec2 ts = invTexSize;
373
374 vec3 color = textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ts.x, uv.y - ts.y, dirLayer.z), 0).xyz * diagCoeff;
375 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x, uv.y - ts.y, dirLayer.z), 0).xyz * stepCoeff;
376 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ts.x, uv.y - ts.y, dirLayer.z), 0).xyz * diagCoeff;
377
378 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ts.x, uv.y, dirLayer.z), 0).xyz * stepCoeff;
379 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x, uv.y, dirLayer.z), 0).xyz * centerCoeff;
380 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ts.x, uv.y, dirLayer.z), 0).xyz * stepCoeff;
381
382 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ts.x, uv.y + ts.y, dirLayer.z), 0).xyz * diagCoeff;
383 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x, uv.y + ts.y, dirLayer.z), 0).xyz * centerCoeff;
384 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ts.x, uv.y + ts.y, dirLayer.z), 0).xyz * diagCoeff;
385
386 // then center square
387 const vec2 ths = ts * 0.5;
388
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 color += textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ths.x, uv.y + ths.y, dirLayer.z), 0).xyz * centerCoeff;
393
394 #else
395
396 const vec2 ths = invTexSize * 0.5;
397
398 // center
399 vec3 color = textureLod(sampler2DArray(tex, sampl), vec3(uv + ths, dirLayer.z), 0).xyz * 0.5;
400 // corners
401 // 1.0 / 8.0 = 0.125
402 color = textureLod(sampler2DArray(tex, sampl), vec3(uv - ths, dirLayer.z), 0).xyz * 0.125 + color;
403 color = textureLod(sampler2DArray(tex, sampl), vec3(uv.x + ths.x, uv.y - ths.y, dirLayer.z), 0).xyz * 0.125 + color;
404 color = textureLod(sampler2DArray(tex, sampl), vec3(uv.x - ths.x, uv.y + ths.y, dirLayer.z), 0).xyz * 0.125 + color;
405 color = textureLod(sampler2DArray(tex, sampl), vec3(uv + ths, dirLayer.z), 0).xyz * 0.125 + color;
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