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