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 #include "render_data_store_default_light.h"
17
18 #include <cstdint>
19
20 #include <3d/render/default_material_constants.h>
21 #include <3d/render/render_data_defines_3d.h>
22 #include <base/containers/array_view.h>
23 #include <core/log.h>
24 #include <render/resource_handle.h>
25
26 CORE3D_BEGIN_NAMESPACE()
27 using namespace BASE_NS;
28 using namespace RENDER_NS;
29
RenderDataStoreDefaultLight(const string_view name)30 RenderDataStoreDefaultLight::RenderDataStoreDefaultLight(const string_view name) : name_(name) {}
31
PostRender()32 void RenderDataStoreDefaultLight::PostRender()
33 {
34 Clear();
35 }
36
Clear()37 void RenderDataStoreDefaultLight::Clear()
38 {
39 lights_.clear();
40 lightCounts_ = {};
41 }
42
SetShadowTypes(const ShadowTypes & shadowTypes,const uint32_t flags)43 void RenderDataStoreDefaultLight::SetShadowTypes(const ShadowTypes& shadowTypes, const uint32_t flags)
44 {
45 shadowTypes_ = shadowTypes;
46 }
47
GetShadowTypes() const48 IRenderDataStoreDefaultLight::ShadowTypes RenderDataStoreDefaultLight::GetShadowTypes() const
49 {
50 return shadowTypes_;
51 }
52
SetShadowQualityResolutions(const ShadowQualityResolutions & resolutions,const uint32_t flags)53 void RenderDataStoreDefaultLight::SetShadowQualityResolutions(
54 const ShadowQualityResolutions& resolutions, const uint32_t flags)
55 {
56 resolutions_ = resolutions;
57 }
58
GetShadowQualityResolution() const59 Math::UVec2 RenderDataStoreDefaultLight::GetShadowQualityResolution() const
60 {
61 if (shadowTypes_.shadowQuality == ShadowQuality::LOW) {
62 return resolutions_.low;
63 } else if (shadowTypes_.shadowQuality == ShadowQuality::NORMAL) {
64 return resolutions_.normal;
65 } else if (shadowTypes_.shadowQuality == ShadowQuality::HIGH) {
66 return resolutions_.high;
67 } else {
68 return resolutions_.ultra;
69 }
70 }
71
AddLight(const RenderLight & light)72 void RenderDataStoreDefaultLight::AddLight(const RenderLight& light)
73 {
74 // drop light that has all components below zero (negative light)
75 constexpr float lightIntensityEpsilon { 0.0001f };
76 if (((light.color.x < 0.0f) && (light.color.y < 0.0f) && (light.color.z < 0.0f)) ||
77 (light.color.w < lightIntensityEpsilon)) {
78 return;
79 }
80
81 RenderLight renderLight = light; // copy
82 // we do not support negative color values for lights
83 renderLight.color.x = Math::max(0.0f, renderLight.color.x);
84 renderLight.color.y = Math::max(0.0f, renderLight.color.y);
85 renderLight.color.z = Math::max(0.0f, renderLight.color.z);
86 const uint32_t lightCount = lightCounts_.directional + lightCounts_.spot + lightCounts_.point;
87 #if (CORE3D_VALIDATION_ENABLED == 1)
88 if (lightCount >= DefaultMaterialLightingConstants::MAX_LIGHT_COUNT) {
89 CORE_LOG_ONCE_W("drop_light_count_", "CORE3D_VALIDATION: light dropped (max count: %u)",
90 DefaultMaterialLightingConstants::MAX_LIGHT_COUNT);
91 }
92 #endif
93 if (lightCount < DefaultMaterialLightingConstants::MAX_LIGHT_COUNT) {
94 if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_DIRECTIONAL_LIGHT_BIT) {
95 lightCounts_.directional++;
96 } else if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_SPOT_LIGHT_BIT) {
97 lightCounts_.spot++;
98 } else if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_POINT_LIGHT_BIT) {
99 lightCounts_.point++;
100 }
101 if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_SHADOW_LIGHT_BIT) {
102 const uint32_t shadowCount = lightCounts_.dirShadow + lightCounts_.spotShadow;
103 if (shadowCount < DefaultMaterialLightingConstants::MAX_SHADOW_COUNT) {
104 if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_DIRECTIONAL_LIGHT_BIT) {
105 lightCounts_.dirShadow++;
106 } else if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_SPOT_LIGHT_BIT) {
107 lightCounts_.spotShadow++;
108 }
109 renderLight.shadowIndex = shadowCount; // shadow index in atlas
110 lightCounts_.shadowCount = lightCounts_.spotShadow + lightCounts_.dirShadow;
111 }
112 }
113 lights_.push_back(move(renderLight));
114 }
115 }
116
GetLights() const117 array_view<const RenderLight> RenderDataStoreDefaultLight::GetLights() const
118 {
119 return array_view<const RenderLight>(lights_);
120 }
121
GetLightCounts() const122 IRenderDataStoreDefaultLight::LightCounts RenderDataStoreDefaultLight::GetLightCounts() const
123 {
124 return lightCounts_;
125 }
126
GetLightingFlags() const127 IRenderDataStoreDefaultLight::LightingFlags RenderDataStoreDefaultLight::GetLightingFlags() const
128 {
129 LightingFlags lightingSpecializationFlags = 0u;
130 if (shadowTypes_.shadowType == IRenderDataStoreDefaultLight::ShadowType::VSM) {
131 lightingSpecializationFlags |= LightingFlagBits::LIGHTING_SHADOW_TYPE_VSM_BIT;
132 }
133 if (lightCounts_.point > 0u) {
134 lightingSpecializationFlags |= LightingFlagBits::LIGHTING_POINT_ENABLED_BIT;
135 }
136 if (lightCounts_.spot > 0u) {
137 lightingSpecializationFlags |= LightingFlagBits::LIGHTING_SPOT_ENABLED_BIT;
138 }
139 return lightingSpecializationFlags;
140 }
141
142 // for plugin / factory interface
Create(RENDER_NS::IRenderContext &,char const * name)143 RENDER_NS::IRenderDataStore* RenderDataStoreDefaultLight::Create(RENDER_NS::IRenderContext&, char const* name)
144 {
145 // engine not needed
146 return new RenderDataStoreDefaultLight(name);
147 }
148
Destroy(IRenderDataStore * instance)149 void RenderDataStoreDefaultLight::Destroy(IRenderDataStore* instance)
150 {
151 delete static_cast<RenderDataStoreDefaultLight*>(instance);
152 }
153 CORE3D_END_NAMESPACE()
154