1 /*
2 * Copyright (c) 2022 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 // offset to DefaultMaterialSingleLightStruct
33 static constexpr uint32_t LIGHT_LIST_OFFSET { 16u * 6u };
34
35 static constexpr bool ENABLE_CLUSTERED_LIGHTING { false };
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, const uint32_t sceneId)
60 {
61 BASE_NS::vector<SortData> sortedFlags(lightCount);
62 uint32_t outIdx = 0U;
63 for (uint32_t inIdx = 0U; inIdx < lightCount; ++inIdx) {
64 if (lights[inIdx].sceneId != sceneId) {
65 continue;
66 }
67 sortedFlags[outIdx].lightUsageFlags = lights[inIdx].lightUsageFlags;
68 sortedFlags[outIdx].index = inIdx;
69 ++outIdx;
70 }
71 sortedFlags.resize(outIdx);
72 std::sort(sortedFlags.begin(), sortedFlags.end(), [](const auto& lhs, const auto& rhs) {
73 return ((lhs.lightUsageFlags & 0x7u) < (rhs.lightUsageFlags & 0x7u));
74 });
75 return sortedFlags;
76 }
77
78 static void CopySingleLight(
79 const RenderLight& currLight, const uint32_t shadowCount, DefaultMaterialSingleLightStruct* memLight)
80 {
81 const float shadowStepSize = 1.0f / BASE_NS::Math::max(1.0f, static_cast<float>(shadowCount));
82 const BASE_NS::Math::Vec4 pos = currLight.pos;
83 const BASE_NS::Math::Vec4 dir = currLight.dir;
84 memLight->pos = pos;
85 memLight->dir = dir;
86 constexpr float epsilonForMinDivisor { 0.0001f };
87 memLight->dir.w = BASE_NS::Math::max(epsilonForMinDivisor, currLight.range);
88 memLight->color =
89 BASE_NS::Math::Vec4(BASE_NS::Math::Vec3(currLight.color) * currLight.color.w, currLight.color.w);
90 memLight->spotLightParams = currLight.spotLightParams;
91 memLight->shadowFactors = { currLight.shadowFactors.x, currLight.shadowFactors.y, currLight.shadowFactors.z,
92 shadowStepSize };
93 memLight->flags = { currLight.lightUsageFlags, currLight.shadowCameraIndex, currLight.shadowIndex,
94 shadowCount };
95 memLight->indices = { static_cast<uint32_t>(currLight.id >> 32U),
96 static_cast<uint32_t>(currLight.id & 0xFFFFffff), static_cast<uint32_t>(currLight.layerMask >> 32U),
97 static_cast<uint32_t>(currLight.layerMask & 0xFFFFffff) };
98 }
99 };
100 CORE3D_END_NAMESPACE()
101
102 #endif // CORE3D_RENDER__NODE__RENDER_LIGHT_HELPER_H
103