1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 /*!
34 \class SoShadowDirectionalLight SoShadowDirectionalLight.h Inventor/annex/FXViz/nodes/SoShadowDirectionalLight.h
35 \brief The SoShadowDirectionalLight class is a node for setting up a directional light which casts shadows.
36
37 Directional lights usually affect everything, but since it's not
38 always feasible to use one shadow map for the entire scene
39 graph. This node has some extra features to work around this.
40
41 It calculates the intersection between the current view volume and
42 either the scene bounding box, or the bounding box provided in this
43 node. The shadows are only calculated for this volume. This means
44 that you'll get more detailed shadows as you zoom in on items in the
45 scene graph.
46
47 In addition, you can set the maximum distance from the camera which
48 will be shaded with shadows. Think of this a new far plane for the
49 camera which only affects shadows.
50
51 As with SoShadowSpotLight, it's possible to optimize further by
52 setting your own shadow caster scene graph in the shadowMapScene
53 field.
54
55 The example scene graph below demonstrates how you can use this node
56 to create shadows on a large number of objects, and still get decent
57 precision when zooming in. To further reduce the volume covered by
58 the shadowmap, you can set \a maxShadowDistance to some number > 0.
59 This is the distance from the camera where shadows will be visible.
60
61 \code
62
63 DirectionalLight {
64 direction 0 0 -1
65 intensity 0.2
66 }
67
68 ShadowGroup {
69 quality 1 # to get per pixel lighting
70 precision 1
71
72 ShadowDirectionalLight {
73 direction 1 1 -1
74 intensity 0.8
75 # enable this to reduce the shadow view distance
76 # maxShadowDistance 200
77 }
78
79 # 900 cubes spaced out over a fairly large area
80 Array {
81 origin CENTER
82 numElements1 30
83 numElements2 30
84 numElements3 1
85 separation1 20 0 0
86 separation2 0 20 0
87 separation3 0 0 0
88
89 Material { diffuseColor 1 0 0 specularColor 1 1 1 }
90 Cube { width 4 height 4 depth 4 }
91 }
92
93 # a chess board
94 Coordinate3 { point [ -400 -400 -3, 400 -400 -3, 400 400 -3, -400 400 -3 ] }
95 Material { specularColor 1 1 1 shininess 0.9 }
96 Complexity { textureQuality 0.1 }
97 Texture2 { image 2 2 3 0xffffff 0x225588 0x225588 0xffffff }
98 Texture2Transform { scaleFactor 20 20 }
99 FaceSet { numVertices 4 }
100 }
101 \endcode
102
103 \since Coin 3.0
104 */
105
106 /*!
107 \var SoSFNode SoShadowDirectionalLight::shadowMapScene
108
109 The shadow map scene graph. If this is NULL (the default), the node
110 will behave as a normal SoDirectionalLight node.
111
112 */
113
114 /*!
115 \var SoSFFloat SoShadowDirectionalLight::maxShadowDistance
116
117 The maximum distance (from the camera) that we'll see shadows from this light source.
118 */
119
120 /*!
121 \var SoSFVec3f SoShadowDirectionalLight::bboxCenter
122
123 Can be used to specify the volume that should be used for
124 calculating the resulting shadow volume.
125 */
126
127 /*!
128 \var SoSFVec3f SoShadowDirectionalLight::bboxSize
129
130 Can be used to specify the volume that should be used for
131 calculating the resulting shadow volume.
132 */
133
134 // *************************************************************************
135
136 #include <Inventor/annex/FXViz/nodes/SoShadowDirectionalLight.h>
137
138 #include <cstdio>
139 #include <Inventor/actions/SoGLRenderAction.h>
140
141 #include "nodes/SoSubNodeP.h"
142
143 // *************************************************************************
144
145
146 SO_NODE_SOURCE(SoShadowDirectionalLight);
147
148 /*!
149 Constructor.
150 */
SoShadowDirectionalLight(void)151 SoShadowDirectionalLight::SoShadowDirectionalLight(void)
152 {
153 SO_NODE_INTERNAL_CONSTRUCTOR(SoShadowDirectionalLight);
154 SO_NODE_ADD_FIELD(shadowMapScene, (NULL));
155 SO_NODE_ADD_FIELD(maxShadowDistance, (-1.0f));
156 SO_NODE_ADD_FIELD(bboxCenter, (0.0f, 0.0f, 0.0f));
157 SO_NODE_ADD_FIELD(bboxSize, (-1.0f, -1.0f, -1.0f));
158 }
159
160 /*!
161 Destructor.
162 */
~SoShadowDirectionalLight()163 SoShadowDirectionalLight::~SoShadowDirectionalLight()
164 {
165 }
166
167 // Doc from superclass.
168 void
initClass(void)169 SoShadowDirectionalLight::initClass(void)
170 {
171 SO_NODE_INTERNAL_INIT_CLASS(SoShadowDirectionalLight, SO_FROM_COIN_4_0);
172 }
173
174 // Doc from superclass.
175 void
GLRender(SoGLRenderAction * action)176 SoShadowDirectionalLight::GLRender(SoGLRenderAction * action)
177 {
178 inherited::GLRender(action);
179 }
180
181 #ifdef COIN_TEST_SUITE
182
BOOST_AUTO_TEST_CASE(initialized)183 BOOST_AUTO_TEST_CASE(initialized)
184 {
185 SoShadowDirectionalLight * node = new SoShadowDirectionalLight;
186 assert(node);
187 node->ref();
188 BOOST_CHECK_MESSAGE(node->getTypeId() != SoType::badType(),
189 "missing class initialization");
190 node->unref();
191 }
192
193 #endif // COIN_TEST_SUITE
194