• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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 
Ref()43 void RenderDataStoreDefaultLight::Ref()
44 {
45     refcnt_.fetch_add(1, std::memory_order_relaxed);
46 }
47 
Unref()48 void RenderDataStoreDefaultLight::Unref()
49 {
50     if (std::atomic_fetch_sub_explicit(&refcnt_, 1, std::memory_order_release) == 1) {
51         std::atomic_thread_fence(std::memory_order_acquire);
52         delete this;
53     }
54 }
55 
GetRefCount()56 int32_t RenderDataStoreDefaultLight::GetRefCount()
57 {
58     return refcnt_;
59 }
60 
SetShadowTypes(const ShadowTypes & shadowTypes,const uint32_t flags)61 void RenderDataStoreDefaultLight::SetShadowTypes(const ShadowTypes& shadowTypes, const uint32_t flags)
62 {
63     shadowTypes_ = shadowTypes;
64 }
65 
GetShadowTypes() const66 IRenderDataStoreDefaultLight::ShadowTypes RenderDataStoreDefaultLight::GetShadowTypes() const
67 {
68     return shadowTypes_;
69 }
70 
SetShadowQualityResolutions(const ShadowQualityResolutions & resolutions,const uint32_t flags)71 void RenderDataStoreDefaultLight::SetShadowQualityResolutions(
72     const ShadowQualityResolutions& resolutions, const uint32_t flags)
73 {
74     resolutions_ = resolutions;
75 }
76 
GetShadowQualityResolution() const77 Math::UVec2 RenderDataStoreDefaultLight::GetShadowQualityResolution() const
78 {
79     if (shadowTypes_.shadowQuality == ShadowQuality::LOW) {
80         return resolutions_.low;
81     } else if (shadowTypes_.shadowQuality == ShadowQuality::NORMAL) {
82         return resolutions_.normal;
83     } else if (shadowTypes_.shadowQuality == ShadowQuality::HIGH) {
84         return resolutions_.high;
85     } else {
86         return resolutions_.ultra;
87     }
88 }
89 
AddLight(const RenderLight & light)90 void RenderDataStoreDefaultLight::AddLight(const RenderLight& light)
91 {
92     // drop light that has all components below zero (negative light)
93     constexpr float lightIntensityEpsilon { 0.0001f };
94     if (((light.color.x < 0.0f) && (light.color.y < 0.0f) && (light.color.z < 0.0f)) ||
95         (light.color.w < lightIntensityEpsilon)) {
96         return;
97     }
98 
99     RenderLight renderLight = light; // copy
100     // we do not support negative color values for lights
101     renderLight.color.x = Math::max(0.0f, renderLight.color.x);
102     renderLight.color.y = Math::max(0.0f, renderLight.color.y);
103     renderLight.color.z = Math::max(0.0f, renderLight.color.z);
104     const uint32_t lightCount = lightCounts_.directional + lightCounts_.spot + lightCounts_.point;
105     if (lightCount >= DefaultMaterialLightingConstants::MAX_LIGHT_COUNT) {
106 #if (CORE3D_VALIDATION_ENABLED == 1)
107         CORE_LOG_ONCE_W("drop_light_count_", "CORE3D_VALIDATION: light dropped (max count: %u)",
108             DefaultMaterialLightingConstants::MAX_LIGHT_COUNT);
109 #endif
110         return;
111     }
112     if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_DIRECTIONAL_LIGHT_BIT) {
113         lightCounts_.directional++;
114     } else if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_SPOT_LIGHT_BIT) {
115         lightCounts_.spot++;
116     } else if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_POINT_LIGHT_BIT) {
117         lightCounts_.point++;
118     }
119     if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_SHADOW_LIGHT_BIT) {
120         const uint32_t shadowCount = lightCounts_.dirShadow + lightCounts_.spotShadow;
121         if (shadowCount < DefaultMaterialLightingConstants::MAX_SHADOW_COUNT) {
122             if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_DIRECTIONAL_LIGHT_BIT) {
123                 lightCounts_.dirShadow++;
124             } else if (renderLight.lightUsageFlags & RenderLight::LIGHT_USAGE_SPOT_LIGHT_BIT) {
125                 lightCounts_.spotShadow++;
126             }
127             renderLight.shadowIndex = shadowCount; // shadow index in atlas
128             lightCounts_.shadowCount = lightCounts_.spotShadow + lightCounts_.dirShadow;
129         }
130     }
131     lights_.push_back(move(renderLight));
132 }
133 
GetLights() const134 array_view<const RenderLight> RenderDataStoreDefaultLight::GetLights() const
135 {
136     return array_view<const RenderLight>(lights_);
137 }
138 
GetLightCounts() const139 IRenderDataStoreDefaultLight::LightCounts RenderDataStoreDefaultLight::GetLightCounts() const
140 {
141     return lightCounts_;
142 }
143 
GetLightingFlags() const144 IRenderDataStoreDefaultLight::LightingFlags RenderDataStoreDefaultLight::GetLightingFlags() const
145 {
146     LightingFlags lightingSpecializationFlags = 0u;
147     if (shadowTypes_.shadowType == IRenderDataStoreDefaultLight::ShadowType::VSM) {
148         lightingSpecializationFlags |= LightingFlagBits::LIGHTING_SHADOW_TYPE_VSM_BIT;
149     }
150     if (lightCounts_.point > 0u) {
151         lightingSpecializationFlags |= LightingFlagBits::LIGHTING_POINT_ENABLED_BIT;
152     }
153     if (lightCounts_.spot > 0u) {
154         lightingSpecializationFlags |= LightingFlagBits::LIGHTING_SPOT_ENABLED_BIT;
155     }
156     return lightingSpecializationFlags;
157 }
158 
159 // for plugin / factory interface
Create(RENDER_NS::IRenderContext &,char const * name)160 refcnt_ptr<IRenderDataStore> RenderDataStoreDefaultLight::Create(RENDER_NS::IRenderContext&, char const* name)
161 {
162     return refcnt_ptr<IRenderDataStore>(new RenderDataStoreDefaultLight(name));
163 }
164 CORE3D_END_NAMESPACE()
165