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_POST_PROCESS_BLOCKS_H
17 #define API_RENDER_SHADERS_COMMON_POST_PROCESS_BLOCKS_H
18 
19 #include "render_color_conversion_common.h"
20 #include "render_post_process_structs_common.h"
21 #include "render_tonemap_common.h"
22 
23 #define CORE_CLAMP_MAX_VALUE 64512.0
24 
25 /**
26  * returns tonemapped color
27  */
PostProcessTonemapBlock(in uint postProcessFlags,in vec4 tonemapFactor,in vec3 inCol,out vec3 outCol)28 void PostProcessTonemapBlock(in uint postProcessFlags, in vec4 tonemapFactor, in vec3 inCol, out vec3 outCol)
29 {
30     outCol = inCol;
31     if ((postProcessFlags & POST_PROCESS_SPECIALIZATION_TONEMAP_BIT) == POST_PROCESS_SPECIALIZATION_TONEMAP_BIT) {
32         const float exposure = tonemapFactor.x;
33         const vec3 x = outCol * exposure;
34         const uint tonemapType = uint(tonemapFactor.w);
35         if (tonemapType == CORE_POST_PROCESS_TONEMAP_ACES) {
36             outCol = TonemapAces(x);
37         } else if (tonemapType == CORE_POST_PROCESS_TONEMAP_ACES_2020) {
38             outCol = TonemapAcesFilmRec2020(x);
39         } else if (tonemapType == CORE_POST_PROCESS_TONEMAP_FILMIC) {
40             const float exposureEstimate = 6.0f;
41             outCol = TonemapFilmic(x * exposureEstimate);
42         }
43     }
44 }
45 
46 /**
47  * returns vignette applied color with vignette values in the range 0-1
48  */
PostProcessVignetteBlock(in uint postProcessFlags,in vec4 vignetteFactor,in vec2 uv,in vec3 inCol,out vec3 outCol)49 void PostProcessVignetteBlock(
50     in uint postProcessFlags, in vec4 vignetteFactor, in vec2 uv, in vec3 inCol, out vec3 outCol)
51 {
52     outCol = inCol;
53     if ((postProcessFlags & POST_PROCESS_SPECIALIZATION_VIGNETTE_BIT) == POST_PROCESS_SPECIALIZATION_VIGNETTE_BIT) {
54         const vec2 uvVal = uv.xy * (vec2(1.0) - uv.yx);
55         CORE_RELAXEDP float vignette = uvVal.x * uvVal.y * vignetteFactor.x * 40.0;
56         vignette = clamp(pow(vignette, vignetteFactor.y), 0.0, 1.0);
57         outCol.rgb *= vignette;
58     }
59 }
60 
61 /**
62  * returns chroma applied color with two additional samples, coefficient in the range 0-1
63  */
PostProcessColorFringeBlock(in uint postProcessFlags,in vec4 chromaFactor,in vec2 uv,in vec2 uvSize,in sampler2D imgSampler,in vec3 inCol,out vec3 outCol)64 void PostProcessColorFringeBlock(in uint postProcessFlags, in vec4 chromaFactor, in vec2 uv, in vec2 uvSize,
65     in sampler2D imgSampler, in vec3 inCol, out vec3 outCol)
66 {
67     outCol = inCol;
68     if ((postProcessFlags & POST_PROCESS_SPECIALIZATION_COLOR_FRINGE_BIT) ==
69         POST_PROCESS_SPECIALIZATION_COLOR_FRINGE_BIT) {
70         // this is cheap chroma
71         const vec2 distUv = (uv - 0.5) * 2.0;
72         const CORE_RELAXEDP float chroma = dot(distUv, distUv) * chromaFactor.y * chromaFactor.x;
73 
74         const vec2 uvDistToImageCenter = chroma * uvSize;
75         const CORE_RELAXEDP float chromaRed =
76             textureLod(imgSampler, uv - vec2(uvDistToImageCenter.x, uvDistToImageCenter.y), 0).x;
77         const CORE_RELAXEDP float chromaBlue =
78             textureLod(imgSampler, uv + vec2(uvDistToImageCenter.x, uvDistToImageCenter.y), 0).z;
79 
80         outCol.r = chromaRed;
81         outCol.b = chromaBlue;
82     }
83 }
84 
85 /**
86  * returns dithered color
87  */
PostProcessDitherBlock(in uint postProcessFlags,in vec4 ditherFactor,in vec2 uv,in vec3 inCol,out vec3 outCol)88 void PostProcessDitherBlock(in uint postProcessFlags, in vec4 ditherFactor, in vec2 uv, in vec3 inCol, out vec3 outCol)
89 {
90     outCol = inCol;
91     if ((postProcessFlags & POST_PROCESS_SPECIALIZATION_DITHER_BIT) == POST_PROCESS_SPECIALIZATION_DITHER_BIT) {
92         const vec2 random01Range = vec2(uv.x * ditherFactor.y, uv.y * ditherFactor.z);
93         outCol += fract(sin(dot(random01Range.xy, vec2(12.9898, 78.233))) * 43758.5453) * ditherFactor.x;
94     }
95 }
96 
97 /**
98  * returns additional color conversion
99  */
PostProcessColorConversionBlock(in uint postProcessFlags,in vec4 colorConversionFactor,in vec3 inCol,out vec3 outCol)100 void PostProcessColorConversionBlock(
101     in uint postProcessFlags, in vec4 colorConversionFactor, in vec3 inCol, out vec3 outCol)
102 {
103     outCol = inCol;
104     if ((postProcessFlags & POST_PROCESS_SPECIALIZATION_COLOR_CONVERSION_BIT) ==
105         POST_PROCESS_SPECIALIZATION_COLOR_CONVERSION_BIT) {
106         const uint conversionType = uint(colorConversionFactor.w);
107         if (conversionType == CORE_POST_PROCESS_COLOR_CONVERSION_SRGB) {
108             outCol.rgb = LinearToSrgb(outCol.rgb);
109         }
110     }
111 }
112 
113 /**
114  * returns bloom combine
115  */
PostProcessBloomCombineBlock(in uint postProcessFlags,in vec4 bloomFactor,in vec2 uv,in sampler2D imgSampler,in sampler2D dirtImgSampler,in vec3 inCol,out vec3 outCol)116 void PostProcessBloomCombineBlock(in uint postProcessFlags, in vec4 bloomFactor, in vec2 uv, in sampler2D imgSampler,
117     in sampler2D dirtImgSampler, in vec3 inCol, out vec3 outCol)
118 {
119     outCol = inCol;
120     if ((postProcessFlags & POST_PROCESS_SPECIALIZATION_BLOOM_BIT) == POST_PROCESS_SPECIALIZATION_BLOOM_BIT) {
121         // NOTE: lower resolution, more samples might be needed
122         const vec3 bloomColor = textureLod(imgSampler, uv, 0).rgb * bloomFactor.z;
123         const vec3 dirtColor = textureLod(dirtImgSampler, uv, 0).rgb * bloomFactor.w;
124         const vec3 bloomCombine = outCol + bloomColor + dirtColor * max(bloomColor.x, max(bloomColor.y, bloomColor.z));
125         outCol.rgb = min(bloomCombine, CORE_CLAMP_MAX_VALUE);
126     }
127 }
128 
129 #endif // API_RENDER_SHADERS_COMMON_POST_PROCESS_BLOCKS_H
130