Panda3D
Loading...
Searching...
No Matches
pssmCameraRig.I
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/**
29 * @brief Sets the maximum pssm distance.
30 * @details This sets the maximum distance in world space until which shadows
31 * are rendered. After this distance, no shadows will be rendered.
32 *
33 * If the distance is below zero, an assertion is triggered.
34 *
35 * @param distance Maximum distance in world space
36 */
37inline void PSSMCameraRig::set_pssm_distance(float distance) {
38 nassertv(distance > 0.0 && distance < 100000.0);
39 _pssm_distance = distance;
40}
41
42/**
43 * @brief Sets the suns distance
44 * @details This sets the distance the cameras will have from the cameras frustum.
45 * This prevents far objects from having no shadows, which can occur when these
46 * objects are between the cameras frustum and the sun, but not inside of the
47 * cameras frustum. Setting the sun distance high enough will move the cameras
48 * away from the camera frustum, being able to cover those distant objects too.
49 *
50 * If the sun distance is set too high, artifacts will occur due to the reduced
51 * range of depth. If a value below zero is passed, an assertion will get
52 * triggered.
53 *
54 * @param distance The sun distance
55 */
56inline void PSSMCameraRig::set_sun_distance(float distance) {
57 nassertv(distance > 0.0 && distance < 100000.0);
58 _sun_distance = distance;
59}
60
61/**
62 * @brief Sets the logarithmic factor
63 * @details This sets the logarithmic factor, which is the core of the algorithm.
64 * PSSM splits the camera frustum based on a linear and a logarithmic factor.
65 * While a linear factor provides a good distribution, it often is not applicable
66 * for wider distances. A logarithmic distribution provides a better distribution
67 * at distance, but suffers from splitting in the near areas.
68 *
69 * The logarithmic factor mixes the logarithmic and linear split distribution,
70 * to get the best of both. A greater factor will make the distribution more
71 * logarithmic, while a smaller factor will make it more linear.
72 *
73 * If the factor is below zero, an ssertion is triggered.
74 *
75 * @param factor The logarithmic factor
76 */
77inline void PSSMCameraRig::set_logarithmic_factor(float factor) {
78 nassertv(factor > 0.0);
79 _logarithmic_factor = factor;
80}
81
82/**
83 * @brief Sets whether to use a fixed film size
84 * @details This controls if a fixed film size should be used. This will cause
85 * the camera rig to cache the current film size, and only change it in case
86 * it gets too small. This provides less flickering when moving, because the
87 * film size will stay roughly constant. However, to prevent the cached film
88 * size getting too big, one should call PSSMCameraRig::reset_film_size
89 * once in a while, otherwise there might be a lot of wasted space.
90 *
91 * @param flag Whether to use a fixed film size
92 */
94 _use_fixed_film_size = flag;
95}
96
97/**
98 * @brief Sets the resolution of each split
99 * @details This sets the resolution of each split. Currently it is equal for
100 * each split. This is required when using PSSMCameraRig::set_use_stable_csm,
101 * to compute how bix a texel is.
102 *
103 * It has to match the y-resolution of the pssm shadow map. If an invalid
104 * resolution is triggered, an assertion is thrown.
105 *
106 * @param resolution The resolution of each split.
107 */
108inline void PSSMCameraRig::set_resolution(size_t resolution) {
109 nassertv(resolution >= 0 && resolution < 65535);
110 _resolution = resolution;
111}
112
113/**
114 * @brief Sets whether to use stable CSM snapping.
115 * @details This option controls if stable CSM snapping should be used. When the
116 * option is enabled, all splits will snap to their texels, so that when moving,
117 * no flickering will occur. However, this only works when the splits do not
118 * change their film size, rotation and angle.
119 *
120 * @param flag Whether to use stable CSM snapping
121 */
122inline void PSSMCameraRig::set_use_stable_csm(bool flag) {
123 _use_stable_csm = flag;
124}
125
126/**
127 * @brief Sets the border bias for each split
128 * @details This sets the border bias for every split. This increases each
129 * splits frustum by multiplying it by (1 + bias), and helps reducing artifacts
130 * at the borders of the splits. Artifacts can occur when the bias is too low,
131 * because then the filtering will go over the bounds of the split, producing
132 * invalid results.
133 *
134 * If the bias is below zero, an assertion is thrown.
135 *
136 * @param bias Border bias
137 */
138inline void PSSMCameraRig::set_border_bias(float bias) {
139 nassertv(bias >= 0.0);
140 _border_bias = bias;
141}
142
143/**
144 * @brief Resets the film size cache
145 * @details In case PSSMCameraRig::set_use_fixed_film_size is used, this resets
146 * the film size cache. This might lead to a small "jump" in the shadows,
147 * because the film size changes, however it leads to a better shadow distribution.
148 *
149 * This is the case because when using a fixed film size, the cache will get
150 * bigger and bigger, whenever the camera moves to a grazing angle. However,
151 * when moving back to a normal angle, the film size cache still stores this
152 * big angle, and thus the splits will have a much bigger film size than actualy
153 * required. To prevent this, call this method once in a while, so an optimal
154 * distribution is ensured.
155 */
157 for (size_t i = 0; i < _max_film_sizes.size(); ++i) {
158 _max_film_sizes[i].fill(0);
159 }
160}
161
162/**
163 * @brief Returns the n-th camera
164 * @details This returns the n-th camera of the camera rig, which can be used
165 * for various stuff like showing its frustum, passing it as a shader input,
166 * and so on.
167 *
168 * The first camera is the camera which is the camera of the first split,
169 * which is the split closest to the camera. All cameras follow in descending
170 * order until to the last camera, which is the split furthest away from the
171 * camera.
172 *
173 * If an invalid index is passed, an assertion is thrown.
174 *
175 * @param index Index of the camera.
176 * @return [description]
177 */
179 nassertr(index >= 0 && index < _cam_nodes.size(), NodePath());
180 return _cam_nodes[index];
181}
182
183/**
184 * @brief Internal method to compute the distance of a split
185 * @details This is the internal method to perform the weighting of the
186 * logarithmic and linear distribution. It computes the distance to the
187 * camera from which a given split starts, by weighting the logarithmic and
188 * linear factor.
189 *
190 * The return value is a value ranging from 0 .. 1. To get the distance in
191 * world space, the value has to get multiplied with the maximum shadow distance.
192 *
193 * @param split_index The index of the split
194 * @return Distance of the split, ranging from 0 .. 1
195 */
196inline float PSSMCameraRig::get_split_start(size_t split_index) {
197 float x = (float)split_index / (float)_cam_nodes.size();
198 return (exp(_logarithmic_factor*x)-1) / (exp(_logarithmic_factor)-1);
199}
200
201/**
202 * @brief Internal method for interpolating a point along the camera frustum
203 * @details This method takes a given distance in the 0 .. 1 range, whereas
204 * 0 denotes the camera near plane, and 1 denotes the camera far plane,
205 * and lineary interpolates between them.
206 *
207 * @param origin Edge of the frustum
208 * @param depth Distance in the 0 .. 1 range
209 *
210 * @return interpolated point in world space
211 */
212inline LPoint3 PSSMCameraRig::get_interpolated_point(CoordinateOrigin origin, float depth) {
213 nassertr(depth >= 0.0 && depth <= 1.0, LPoint3());
214 return _curr_near_points[origin] * (1.0 - depth) + _curr_far_points[origin] * depth;
215}
216
217/**
218 * @brief Returns a handle to the MVP array
219 * @details This returns a handle to the array of view-projection matrices
220 * of the different splits. This can be used for computing shadows. The array
221 * is a PTALMatrix4 and thus can be directly bound to a shader.
222 *
223 * @return view-projection matrix array
224 */
225inline const PTA_LMatrix4 &PSSMCameraRig::get_mvp_array() {
226 return _camera_mvps;
227}
228
229/**
230 * @brief Returns a handle to the near and far planes array
231 * @details This returns a handle to the near and far plane array. Each split
232 * has an entry in the array, whereas the x component of the vecto denotes the
233 * near plane, and the y component denotes the far plane of the split.
234 *
235 * This is required because the near and far planes of the splits change
236 * constantly. To access them in a shader, the shader needs access to the
237 * array.
238 *
239 * @return Array of near and far planes
240 */
241inline const PTA_LVecBase2 &PSSMCameraRig::get_nearfar_array() {
242 return _camera_nearfar;
243}
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
void set_pssm_distance(float distance)
RenderPipeline.
const PTA_LVecBase2 & get_nearfar_array()
Returns a handle to the near and far planes array.
void set_use_stable_csm(bool flag)
Sets whether to use stable CSM snapping.
void set_border_bias(float bias)
Sets the border bias for each split.
void set_sun_distance(float distance)
Sets the suns distance.
void reset_film_size_cache()
Resets the film size cache.
NodePath get_camera(size_t index)
Returns the n-th camera.
const PTA_LMatrix4 & get_mvp_array()
Returns a handle to the MVP array.
void set_use_fixed_film_size(bool flag)
Sets whether to use a fixed film size.
void set_logarithmic_factor(float factor)
Sets the logarithmic factor.
void set_resolution(size_t resolution)
Sets the resolution of each split.