28 #include "internalLightManager.h" 34 NotifyCategoryDef(lightmgr,
"");
44 _shadow_update_distance = 100.0;
46 _shadow_manager =
nullptr;
70 nassertv(_shadow_manager !=
nullptr);
74 lightmgr_cat.error() <<
"could not add light because it already is attached! " 75 <<
"Detach the light first, then try it again." << endl;
82 lightmgr_cat.error() <<
"Light limit of " << MAX_LIGHT_COUNT <<
" reached, " 83 <<
"all light slots used!" << endl;
104 gpu_update_light(light);
118 void InternalLightManager::setup_shadows(
RPLight* light) {
122 light->init_shadow_sources();
123 light->update_shadow_sources();
131 lightmgr_cat.error() <<
"Failed to find slot for shadow sources! " 132 <<
"Shadow-Source limit of " << MAX_SHADOW_SOURCES
133 <<
" reached!" << endl;
138 for (
size_t i = 0; i < num_sources; ++i) {
146 size_t slot = base_slot + i;
172 nassertv(_shadow_manager !=
nullptr);
175 lightmgr_cat.error() <<
"Could not detach light, light was not attached!" << endl;
183 gpu_remove_light(light);
235 void InternalLightManager::gpu_remove_consecutive_sources(
ShadowSource *first_source,
236 size_t num_sources) {
237 nassertv(_cmd_list !=
nullptr);
239 GPUCommand cmd_remove(GPUCommand::CMD_remove_sources);
240 cmd_remove.push_int(first_source->
get_slot());
241 cmd_remove.push_int(num_sources);
255 void InternalLightManager::gpu_remove_light(
RPLight* light) {
256 nassertv(_cmd_list !=
nullptr);
258 GPUCommand cmd_remove(GPUCommand::CMD_remove_light);
259 cmd_remove.push_int(light->
get_slot());
274 void InternalLightManager::gpu_update_light(
RPLight* light) {
275 nassertv(_cmd_list !=
nullptr);
277 GPUCommand cmd_update(GPUCommand::CMD_store_light);
278 cmd_update.push_int(light->
get_slot());
294 void InternalLightManager::gpu_update_source(
ShadowSource* source) {
295 nassertv(_cmd_list !=
nullptr);
297 GPUCommand cmd_update(GPUCommand::CMD_store_source);
298 cmd_update.push_int(source->
get_slot());
309 void InternalLightManager::update_lights() {
310 for (
auto iter = _lights.
begin(); iter != _lights.
end(); ++iter) {
314 light->update_shadow_sources();
316 gpu_update_light(light);
341 PN_stdfloat dist_a = (_camera_pos - a->
get_bounds().get_center()).length_squared();
342 PN_stdfloat dist_b = (_camera_pos - a->
get_bounds().get_center()).length_squared();
347 return dist_b > dist_a;
357 void InternalLightManager::update_shadow_sources() {
360 std::vector<ShadowSource*> sources_to_update;
361 for (
auto iter = _shadow_sources.
begin(); iter != _shadow_sources.
end(); ++iter) {
367 PN_stdfloat distance_to_camera = (_camera_pos - bounds.get_center()).length() - bounds.get_radius();
368 if (distance_to_camera < _shadow_update_distance) {
370 sources_to_update.push_back(source);
389 std::sort(sources_to_update.begin(), sources_to_update.end(), [
this](
const ShadowSource* a,
const ShadowSource* b) {
390 return this->compare_shadow_sources(a, b);
398 size_t update_slots = std::min(sources_to_update.size(),
400 for(
size_t i = 0; i < update_slots; ++i) {
401 if (sources_to_update[i]->has_region()) {
402 atlas->free_region(sources_to_update[i]->get_region());
407 for (
size_t i = 0; i < update_slots; ++i) {
412 lightmgr_cat.error() <<
"ShadowManager ensured update slot, but slot is taken!" << endl;
418 size_t region_size = atlas->get_required_tiles(source->
get_resolution());
419 LVecBase4i new_region = atlas->find_and_reserve_region(region_size, region_size);
420 LVecBase4 new_uv_region = atlas->region_to_uv(new_region);
421 source->
set_region(new_region, new_uv_region);
425 gpu_update_source(source);
438 nassertv(_shadow_manager !=
nullptr);
439 nassertv(_cmd_list !=
nullptr);
442 update_shadow_sources();
get_num_update_slots_left
Returns how many update slots are left.
void write_to_command(GPUCommand &cmd) const
Writes the source to a GPUCommand.
void set_needs_update(bool flag)
Sets the update flag of the source.
int get_slot() const
Returns the slot of the shadow source.
This defines a bounding sphere, consisting of a center and a radius.
void set_needs_update(bool flag)
Sets whether the light needs an update.
size_t get_resolution() const
Returns the resolution of the source.
const BoundingSphere & get_bounds() const
Returns the shadow sources bounds.
void set_slot(int slot)
Assigns the source a slot.
size_t get_num_shadow_sources() const
RenderPipeline.
get_casts_shadows
Returns whether the light casts shadows.
ShadowSource * get_shadow_source(size_t index) const
Returns the n-th shadow source.
bool has_slot() const
Returns whether the source has a slot.
const LVecBase4i & get_region() const
Returns the assigned region of the source in atlas space.
bool get_needs_update() const
Returns whether the light needs an update.
InternalContainer::iterator end()
Returns an iterator to the end of the container.
bool add_update(const ShadowSource *source)
Adds a new shadow update.
bool get_needs_update() const
RenderPipeline.
void reserve_slot(size_t slot, T ptr)
Reserves a slot.
void add_light(PT(RPLight) light)
Adds a new light.
void update()
Main update method.
get_atlas
Returns a handle to the shadow atlas.
void clear_shadow_sources()
Clears all shadow source.
bool has_slot() const
Returns whether the light has a slot.
void ref() const
Explicitly increments the reference count.
Class which manages distributing shadow maps in an atlas.
virtual void write_to_command(GPUCommand &cmd)
Writes the light to a GPUCommand.
bool has_region() const
Returns whether the source has a valid region.
bool find_consecutive_slots(size_t &slot, size_t num_consecutive) const
Finds free consecutive slots.
bool find_slot(size_t &slot) const
Finds a free slot.
Class for storing data to be transferred to the GPU.
void remove_slot()
Removes the light slot.
void add_command(const GPUCommand &cmd)
Pushes a GPUCommand to the command list.
void set_region(const LVecBase4i ®ion, const LVecBase4 ®ion_uv)
Sets the assigned region of the source in atlas and uv space.
void remove_light(PT(RPLight) light)
Removes a light.
void assign_slot(int slot)
Assigns a slot to the light.
int get_slot() const
Returns the slot of the light.
void free_slot(size_t slot)
Frees an allocated slot.
InternalLightManager()
Constructs the light manager.
virtual bool unref() const
Explicitly decrements the reference count.
InternalContainer::iterator begin()
Returns an iterator to the begin of the container.
void clear_region()
Clears the assigned region of the source.