28#include "internalLightManager.h"
34NotifyCategoryDef(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;
81 if (!_lights.find_slot(slot)) {
82 lightmgr_cat.error() <<
"Light limit of " << MAX_LIGHT_COUNT <<
" reached, "
83 <<
"all light slots used!" << endl;
94 _lights.reserve_slot(slot, light);
104 gpu_update_light(light);
118void 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;
147 _shadow_sources.reserve_slot(slot, source);
172 nassertv(_shadow_manager !=
nullptr);
175 lightmgr_cat.error() <<
"Could not detach light, light was not attached!" << endl;
180 _lights.free_slot(light->
get_slot());
183 gpu_remove_light(light);
198 _shadow_sources.free_slot(source->
get_slot());
201 _shadow_manager->get_atlas()->free_region(source->
get_region());
235void 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);
255void 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());
260 _cmd_list->add_command(cmd_remove);
274void 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());
281 _cmd_list->add_command(cmd_update);
294void 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());
300 _cmd_list->add_command(cmd_update);
309void InternalLightManager::update_lights() {
310 for (
auto iter = _lights.begin(); iter != _lights.end(); ++iter) {
311 RPLight* light = *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;
357void InternalLightManager::update_shadow_sources() {
360 std::vector<ShadowSource*> sources_to_update;
361 for (
auto iter = _shadow_sources.begin(); iter != _shadow_sources.end(); ++iter) {
362 ShadowSource* source = *iter;
364 const BoundingSphere& bounds = source->
get_bounds();
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);
377 _shadow_manager->get_atlas()->free_region(source->
get_region());
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);
394 ShadowAtlas *atlas = _shadow_manager->get_atlas();
398 size_t update_slots = std::min(sources_to_update.size(),
399 _shadow_manager->get_num_update_slots_left());
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) {
408 ShadowSource *source = sources_to_update[i];
410 if(!_shadow_manager->add_update(source)) {
412 lightmgr_cat.error() <<
"ShadowManager ensured update slot, but slot is taken!" << endl;
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();
void add_command(const GPUCommand &cmd)
Pushes a GPUCommand to the command list.
Class for storing data to be transferred to the GPU.
void add_light(PT(RPLight) light)
Adds a new light.
void remove_light(PT(RPLight) light)
Removes a light.
void update()
Main update method.
InternalLightManager()
Constructs the light manager.
bool find_consecutive_slots(size_t &slot, size_t num_consecutive) const
Finds free consecutive slots.
get_casts_shadows
Returns whether the light casts shadows.
void clear_shadow_sources()
Clears all shadow source.
ShadowSource * get_shadow_source(size_t index) const
Returns the n-th shadow source.
bool has_slot() const
Returns whether the light has a slot.
virtual void write_to_command(GPUCommand &cmd)
Writes the light to a GPUCommand.
void assign_slot(int slot)
Assigns a slot to the light.
size_t get_num_shadow_sources() const
RenderPipeline.
int get_slot() const
Returns the slot of the light.
void remove_slot()
Removes the light slot.
void set_needs_update(bool flag)
Sets whether the light needs an update.
bool get_needs_update() const
Returns whether the light needs an update.
void ref() const
Explicitly increments the reference count.
virtual bool unref() const
Explicitly decrements the reference count.
LVecBase4i find_and_reserve_region(size_t tile_width, size_t tile_height)
Finds space for a map of the given size in the atlas.
void free_region(const LVecBase4i ®ion)
Frees a given region.
LVecBase4 region_to_uv(const LVecBase4i ®ion)
Converts a tile-space region to uv space.
int get_required_tiles(size_t resolution) const
Returns the amount of tiles required to store a resolution.
size_t get_resolution() const
Returns the resolution of the source.
int get_slot() const
Returns the slot of the shadow source.
const LVecBase4i & get_region() const
Returns the assigned region of the source in atlas space.
bool has_region() const
Returns whether the source has a valid region.
void set_slot(int slot)
Assigns the source a slot.
void set_region(const LVecBase4i ®ion, const LVecBase4 ®ion_uv)
Sets the assigned region of the source in atlas and uv space.
void write_to_command(GPUCommand &cmd) const
Writes the source to a GPUCommand.
const BoundingSphere & get_bounds() const
Returns the shadow sources bounds.
void clear_region()
Clears the assigned region of the source.
void set_needs_update(bool flag)
Sets the update flag of the source.
bool get_needs_update() const
RenderPipeline.
bool has_slot() const
Returns whether the source has a slot.