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 CORE3D_RENDER__NODE__RENDER_LIGHT_HELPER_H
17 #define CORE3D_RENDER__NODE__RENDER_LIGHT_HELPER_H
18 
19 // NOTE: do not include this helper file in header
20 
21 #include <algorithm>
22 
23 #include <3d/namespace.h>
24 #include <3d/render/intf_render_data_store_default_light.h>
25 
CORE3D_BEGIN_NAMESPACE()26 CORE3D_BEGIN_NAMESPACE()
27 class RenderLightHelper final {
28 public:
29     RenderLightHelper() = default;
30     ~RenderLightHelper() = default;
31 
32     // NOTE: temporary, no cluster calculations yet
33     static constexpr uint32_t DEFAULT_CLUSTER_INDEX_COUNT { 256u };
34     // offset to DefaultMaterialSingleLightStruct
35     static constexpr uint32_t LIGHT_LIST_OFFSET { 16u * 6u };
36 
37     struct LightCounts {
38         uint32_t directionalLightCount { 0u };
39         uint32_t pointLightCount { 0u };
40         uint32_t spotLightCount { 0u };
41     };
42 
43     static BASE_NS::Math::Vec4 GetShadowAtlasSizeInvSize(const IRenderDataStoreDefaultLight& dsLight)
44     {
45         const BASE_NS::Math::UVec2 shadowQualityRes = dsLight.GetShadowQualityResolution();
46         const uint32_t shadowCount = dsLight.GetLightCounts().shadowCount;
47         BASE_NS::Math::Vec2 size = { float(shadowQualityRes.x * shadowCount), float(shadowQualityRes.y) };
48         size.x = BASE_NS::Math::max(1.0f, size.x);
49         size.y = BASE_NS::Math::max(1.0f, size.y);
50         return { size.x, size.y, 1.0f / size.x, 1.0f / size.y };
51     }
52 
53     struct SortData {
54         RenderLight::LightUsageFlags lightUsageFlags { 0u };
55         uint32_t index { 0u };
56     };
57 
58     static BASE_NS::vector<SortData> SortLights(
59         const BASE_NS::array_view<const RenderLight> lights, const uint32_t lightCount)
60     {
61         BASE_NS::vector<SortData> sortedFlags(lightCount);
62         for (uint32_t idx = 0; idx < lightCount; ++idx) {
63             sortedFlags[idx].lightUsageFlags = lights[idx].lightUsageFlags;
64             sortedFlags[idx].index = idx;
65         }
66         std::sort(sortedFlags.begin(), sortedFlags.end(), [](const auto& lhs, const auto& rhs) {
67             return ((lhs.lightUsageFlags & 0x7u) < (rhs.lightUsageFlags & 0x7u));
68         });
69         return sortedFlags;
70     }
71 
72     static void CopySingleLight(
73         const RenderLight& currLight, const uint32_t shadowCount, DefaultMaterialSingleLightStruct* memLight)
74     {
75         const float shadowStepSize = 1.0f / BASE_NS::Math::max(1.0f, static_cast<float>(shadowCount));
76         const BASE_NS::Math::Vec4 pos = currLight.pos;
77         const BASE_NS::Math::Vec4 dir = currLight.dir;
78         memLight->pos = pos;
79         memLight->dir = dir;
80         constexpr float epsilonForMinDivisor { 0.0001f };
81         memLight->dir.w = BASE_NS::Math::max(epsilonForMinDivisor, currLight.range);
82         memLight->color =
83             BASE_NS::Math::Vec4(BASE_NS::Math::Vec3(currLight.color) * currLight.color.w, currLight.color.w);
84         memLight->spotLightParams = currLight.spotLightParams;
85         memLight->shadowFactors = { currLight.shadowFactors.x, currLight.shadowFactors.y, currLight.shadowFactors.z,
86             shadowStepSize };
87         memLight->flags = { currLight.lightUsageFlags, currLight.shadowCameraIndex, currLight.shadowIndex,
88             shadowCount };
89         memLight->indices = { static_cast<uint32_t>(currLight.id >> 32U),
90             static_cast<uint32_t>(currLight.id & 0xFFFFffff), static_cast<uint32_t>(currLight.layerMask >> 32U),
91             static_cast<uint32_t>(currLight.layerMask & 0xFFFFffff) };
92     }
93 };
94 CORE3D_END_NAMESPACE()
95 
96 #endif // CORE3D_RENDER__NODE__RENDER_LIGHT_HELPER_H
97