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 SHADERS__COMMON__3D_DM_INDIRECT_LIGHTING_COMMON_H
17 #define SHADERS__COMMON__3D_DM_INDIRECT_LIGHTING_COMMON_H
18 
19 #include "3d/shaders/common/3d_dm_structures_common.h"
20 #include "render/shaders/common/render_compatibility_common.h"
21 
22 #ifdef VULKAN
23 
24 #define CORE3D_BRDF_PI 3.14159265359
25 // Avoid divisions by 0 on devices that do not support denormals (from Filament documentation)
26 #define CORE3D_BRDF_MIN_ROUGHNESS 0.089
27 #define CORE3D_HDR_FLOAT_CLAMP_MAX_VALUE 64512.0
28 #define CORE3D_PBR_LIGHTING_EPSILON 0.0001
29 
30 /*
31 Unpack environment color.
32 */
33 // RGBD or just RGB -> ALPHA = 1.0
unpackEnvMap(vec4 envColorRgbd)34 vec3 unpackEnvMap(vec4 envColorRgbd)
35 {
36     return envColorRgbd.xyz * (1.0 / envColorRgbd.a);
37 }
38 
39 // RGBD or just RGB -> ALPHA = 1.0
unpackIblRadiance(vec4 envColorRgbd)40 vec3 unpackIblRadiance(vec4 envColorRgbd)
41 {
42     return envColorRgbd.xyz * (1.0 / envColorRgbd.a);
43 }
44 
45 // build-in (1.0 / PI)
unpackIblIrradianceSH(vec3 n,vec4 sh[CORE_DEFAULT_MATERIAL_MAX_SH_VEC3_VALUE_COUNT])46 vec3 unpackIblIrradianceSH(vec3 n, vec4 sh[CORE_DEFAULT_MATERIAL_MAX_SH_VEC3_VALUE_COUNT])
47 {
48     // use 3 bands spherical harmonics
49     return max(vec3(0.0), sh[0].xyz
50 
51                               + sh[1].xyz * n.y + sh[2].xyz * n.z + sh[3].xyz * n.x
52 
53                               + sh[4].xyz * (n.x * n.y) + sh[5].xyz * (n.z * n.y) +
54                               sh[6].xyz * ((3.0 * n.z * n.z) - 1.0) + sh[7].xyz * (n.x * n.z) +
55                               sh[8].xyz * (n.x * n.x - n.y * n.y));
56 }
57 
58 // https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
59 // alpha taken into account
EnvBRDFApprox(vec3 f0,float roughness,float NoV)60 vec3 EnvBRDFApprox(vec3 f0, float roughness, float NoV)
61 {
62     const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
63     const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
64     vec4 r = roughness * c0 + c1;
65     float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
66     vec2 ab = vec2(-1.04, 1.04) * a004 + r.zw;
67     // f0 has baked transparency, ab.y needs to take alpha into account
68     // 2% f0, takes into account alpha
69     const float f90 = clamp(50.0 * max(f0.x, max(f0.y, f0.z)), 0.0, 1.0);
70     return f0 * ab.x + ab.y * f90;
71 }
72 
73 // https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
74 // Approximation of EnvBRDFApprox for non metallic (diaelectric) materials with reflectance value of 0.04
EnvBRDFApproxNonmetal(float Roughness,float NoV)75 float EnvBRDFApproxNonmetal(float Roughness, float NoV)
76 {
77     // Same as EnvBRDFApprox( 0.04, Roughness, NoV )
78     const vec2 c0 = { -1, -0.0275 };
79     const vec2 c1 = { 1, 0.0425 };
80     vec2 r = Roughness * c0 + c1;
81     return min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y; // 9.28 : param
82 }
83 
84 #endif // VULKAN
85 
86 #endif // SHADERS__COMMON__3D_DM_INDIRECT_LIGHTING_COMMON_H
87