Panda3D
Loading...
Searching...
No Matches
shadowManager.cxx
1/**
2 *
3 * RenderPipeline
4 *
5 * Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#include "shadowManager.h"
29
30NotifyCategoryDef(shadowmanager, "");
31
32/**
33 * @brief Constructs a new shadow atlas
34 * @details This constructs a new shadow atlas. There are a set of properties
35 * which should be set before calling ShadowManager::init, see the set-Methods.
36 * After all properties are set, ShadowManager::init should get called.
37 * ShadowManager::update should get called on a per frame basis.
38 */
40 _max_updates = 10;
41 _atlas = nullptr;
42 _atlas_size = 4096;
43 _tag_state_mgr = nullptr;
44 _atlas_graphics_output = nullptr;
45}
46
47/**
48 * @brief Destructs the ShadowManager
49 * @details This destructs the shadow manager, clearing all resources used
50 */
52 delete _atlas;
53
54 // Todo: Could eventually unregister all shadow cameras. Since the tag state
55 // manager does this on cleanup already, and we get destructed at the same
56 // time (if at all), this is not really necessary
57}
58
59
60/**
61 * @brief Initializes the ShadowManager.
62 * @details This initializes the ShadowManager. All properties should have
63 * been set before calling this, otherwise assertions will get triggered.
64 *
65 * This setups everything required for rendering shadows, including the
66 * shadow atlas and the various shadow cameras. After calling this method,
67 * no properties can be changed anymore.
68 */
70 nassertv(!_scene_parent.is_empty()); // Scene parent not set, call set_scene_parent before init!
71 nassertv(_tag_state_mgr != nullptr); // TagStateManager not set, call set_tag_state_mgr before init!
72 nassertv(_atlas_graphics_output != nullptr); // AtlasGraphicsOutput not set, call set_atlas_graphics_output before init!
73
74 _cameras.resize(_max_updates);
75 _display_regions.resize(_max_updates);
76 _camera_nps.reserve(_max_updates);
77
78 // Create the cameras and regions
79 for(size_t i = 0; i < _max_updates; ++i) {
80
81 // Create the camera
82 PT(Camera) camera = new Camera("ShadowCam-" + format_string(i));
83 camera->set_lens(new MatrixLens());
84 camera->set_active(false);
85 camera->set_scene(_scene_parent);
86 _tag_state_mgr->register_camera("shadow", camera);
87 _camera_nps.push_back(_scene_parent.attach_new_node(camera));
88 _cameras[i] = camera;
89
90 // Create the display region
91 PT(DisplayRegion) region = _atlas_graphics_output->make_display_region();
92 region->set_sort(1000);
93 region->set_clear_depth_active(true);
94 region->set_clear_depth(1.0);
95 region->set_clear_color_active(false);
96 region->set_camera(_camera_nps[i]);
97 region->set_active(false);
98 _display_regions[i] = region;
99 }
100
101 // Create the atlas
102 _atlas = new ShadowAtlas(_atlas_size);
103
104 // Reserve enough space for the updates
105 _queued_updates.reserve(_max_updates);
106}
107
108
109/**
110 * @brief Updates the ShadowManager
111 * @details This updates the ShadowManager, processing all shadow sources which
112 * need to get updated.
113 *
114 * This first collects all sources which require an update, sorts them by priority,
115 * and then processes the first <max_updates> ShadowSources.
116 *
117 * This may not get called before ShadowManager::init, or an assertion will be
118 * thrown.
119 */
121 nassertv(_atlas != nullptr); // ShadowManager::init not called yet
122 nassertv(_queued_updates.size() <= _max_updates); // Internal error, should not happen
123
124 // Disable all cameras and regions which will not be used
125 for (size_t i = _queued_updates.size(); i < _max_updates; ++i) {
126 _cameras[i]->set_active(false);
127 _display_regions[i]->set_active(false);
128 }
129
130 // Iterate over all queued updates
131 for (size_t i = 0; i < _queued_updates.size(); ++i) {
132 const ShadowSource* source = _queued_updates[i];
133
134 // Enable the camera and display region, so they perform a render
135 _cameras[i]->set_active(true);
136 _display_regions[i]->set_active(true);
137
138 // Set the view projection matrix
139 DCAST(MatrixLens, _cameras[i]->get_lens())->set_user_mat(source->get_mvp());
140
141 // Optional: Show the camera frustum for debugging
142 // _cameras[i]->show_frustum();
143
144 // Set the correct dimensions on the display region
145 const LVecBase4& uv = source->get_uv_region();
146 _display_regions[i]->set_dimensions(
147 uv.get_x(), // left
148 uv.get_x() + uv.get_z(), // right
149 uv.get_y(), // bottom
150 uv.get_y() + uv.get_w() // top
151 );
152 }
153
154 // Clear the update list
155 _queued_updates.clear();
156 _queued_updates.reserve(_max_updates);
157}
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition camera.h:35
A rectangular subregion within a window for rendering into.
set_sort
Sets the sort value associated with the DisplayRegion.
DisplayRegion * make_display_region()
Creates a new DisplayRegion that covers the entire window.
A completely generic linear lens.
Definition matrixLens.h:28
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition nodePath.I:188
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
Definition nodePath.cxx:599
Class which manages distributing shadow maps in an atlas.
Definition shadowAtlas.h:41
void init()
Initializes the ShadowManager.
~ShadowManager()
Destructs the ShadowManager.
void update()
Updates the ShadowManager.
ShadowManager()
Constructs a new shadow atlas.
RenderPipeline.
const LMatrix4 & get_mvp() const
Returns the View-Projection matrix of the source.
const LVecBase4 & get_uv_region() const
Returns the assigned region of the source in UV space.
void register_camera(const std::string &state, Camera *source)
RenderPipeline.