Panda3D
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  */
37 inline 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  */
56 inline 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  */
77 inline 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  */
108 inline 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  */
122 inline 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  */
138 inline 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  */
178 inline NodePath PSSMCameraRig::get_camera(size_t index) {
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  */
196 inline 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  */
212 inline 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  */
225 inline 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  */
241 inline const PTA_LVecBase2 &PSSMCameraRig::get_nearfar_array() {
242  return _camera_nearfar;
243 }
void set_border_bias(float bias)
Sets the border bias for each split.
void set_use_fixed_film_size(bool flag)
Sets whether to use a fixed film size.
Definition: pssmCameraRig.I:93
void set_pssm_distance(float distance)
RenderPipeline.
Definition: pssmCameraRig.I:37
const PTA_LVecBase2 & get_nearfar_array()
Returns a handle to the near and far planes array.
NodePath get_camera(size_t index)
Returns the n-th camera.
void set_sun_distance(float distance)
Sets the suns distance.
Definition: pssmCameraRig.I:56
const PTA_LMatrix4 & get_mvp_array()
Returns a handle to the MVP array.
void set_resolution(size_t resolution)
Sets the resolution of each split.
void set_logarithmic_factor(float factor)
Sets the logarithmic factor.
Definition: pssmCameraRig.I:77
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
void set_use_stable_csm(bool flag)
Sets whether to use stable CSM snapping.
void reset_film_size_cache()
Resets the film size cache.