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;
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();
This defines a bounding sphere, consisting of a center and a radius.
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.
void free_slot(size_t slot)
Frees an allocated slot.
InternalContainer::iterator begin()
Returns an iterator to the begin of the container.
bool find_slot(size_t &slot) const
Finds a free slot.
bool find_consecutive_slots(size_t &slot, size_t num_consecutive) const
Finds free consecutive slots.
InternalContainer::iterator end()
Returns an iterator to the end of the container.
void reserve_slot(size_t slot, T ptr)
Reserves a slot.
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.
Class which manages distributing shadow maps in an atlas.
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.
bool add_update(const ShadowSource *source)
Adds a new shadow update.
get_atlas
Returns a handle to the shadow atlas.
get_num_update_slots_left
Returns how many update slots are left.
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.