OSDN Git Service

SDK:
[mikumikustudio/MikuMikuStudio.git] / sdk / jme3-documentation / src / com / jme3 / gde / docs / jme3 / advanced / light_and_shadow.html
1
2 <h1><a>Light and Shadow</a></h1>
3 <div>
4
5 <p>
6
7 <img src="nbdocs:/com/jme3/gde/docs/jme3/advanced/shading-ani.gif">
8 </p>
9
10 <p>
11 Light and Shadow are two separate things in 3D engines, although we percieve them together in real life:
12 </p>
13 <ul>
14 <li><div> Lighting means that an object is brighter on the side facing the light direction, and darker on the backside. Computationally, this is relatively easy. </div>
15 </li>
16 <li><div> Lighting does not mean that objects cast a shadow on the floor or other objects: Activating shadow processing is an additional step described here. Since casting shadows has an impact on performance, drop shadows and ambient occlusion shading are not activated by default.</div>
17 </li>
18 </ul>
19
20 <p>
21
22 <p><div>A light source with a direction or location is required for all Geometries with Lighting.j3md-based Materials. An ambient light is not sufficient. In a scene with no appropriate light sources, Geometries with Lighting.j3md-based Materials do not render. Only Geometries with Unshaded.j3md-based Materials are visible independent of any light sources.
23 </div></p>
24 </p>
25
26 </div>
27 <!-- EDIT1 SECTION "Light and Shadow" [1-1017] -->
28 <h2><a>Light Sources and Colors</a></h2>
29 <div>
30
31 <p>
32
33 <img src="nbdocs:/com/jme3/gde/docs/jme3/advanced/light-sources.png">
34 </p>
35
36 <p>
37 You can add several types of light sources to a scene using <code>rootNode.addLight(mylight)</code>. 
38 </p>
39
40 <p>
41 The available light sources in <code>com.???jme3.???light</code> are:
42 </p>
43 <ul>
44 <li><div> SpotLight </div>
45 </li>
46 <li><div> PointLight</div>
47 </li>
48 <li><div> AmbientLight</div>
49 </li>
50 <li><div> DirectionalLight</div>
51 </li>
52 </ul>
53
54 <p>
55
56 You control the color and intensity of each light source. Typically you set the color to white (<code>new ColorRGBA(1.0f,1.0f,1.0f,1.0f)</code> or <code>ColorRGBA.White</code>), which makes all scene elements appear in their natural color. 
57 </p>
58
59 <p>
60 You can choose to use lights in other colors than white, or darker colors. This influences the scene&#039;s atmosphere and will make the scene appear colder (e.g. <code>ColorRGBA.Cyan</code>) or warmer (<code>ColorRGBA.Yellow</code>), brighter (higher values) or darker (lower values).
61 </p>
62
63 <p>
64 You can get a list of all lights added to a Spatial by calling <code>getWorldLightList()</code> (includes inherited lights) or <code>getLocalLightList()</code> (only directly added lights), and iterating over the result.
65 </p>
66
67 </div>
68 <!-- EDIT2 SECTION "Light Sources and Colors" [1018-2059] -->
69 <h3><a>PointLight</a></h3>
70 <div>
71
72 <p>
73
74 <img src="nbdocs:/com/jme3/gde/docs/jme3/advanced/elephant-pointlights.png">
75 </p>
76
77 <p>
78 A PointLight has a location and shines from there in all directions as far as its radius reaches. The light intensity decreases with increased distance from the light source. A PointLight can at the moment not be used for casting shadows (using the PssmShadowRenderer - read more about this below). 
79 </p>
80
81 <p>
82 <strong>Typical example:</strong> Lamp, lightbulb, torch, candle.
83 </p>
84 <pre>PointLight lamp_light = new PointLight&#40;&#41;;
85 lamp_light.setColor&#40;ColorRGBA.Yellow&#41;;
86 lamp_light.setRadius&#40;4f&#41;;
87 lamp_light.setPosition&#40;new Vector3f&#40;lamp_geo.getLocalTranslation&#40;&#41;&#41;&#41;;
88 rootNode.addLight&#40;lamp_light&#41;;</pre>
89
90 </div>
91 <!-- EDIT3 SECTION "PointLight" [2060-2762] -->
92 <h3><a>DirectionalLight</a></h3>
93 <div>
94
95 <p>
96
97 <img src="nbdocs:/com/jme3/gde/docs/jme3/advanced/house-directionallight.png">
98 </p>
99
100 <p>
101 A DirectionalLight has no position, only a direction. It sends out parallel beams of light and is considered &quot;infinitely&quot; far away. You typically have one directional light per scene. A DirectionalLight can be used together with shadows. 
102 </p>
103
104 <p>
105 <strong>Typically example:</strong> Sun light.
106 </p>
107 <pre>DirectionalLight sun = new DirectionalLight&#40;&#41;;
108 sun.setColor&#40;ColorRGBA.White&#41;;
109 sun.setDirection&#40;new Vector3f&#40;-.5f,-.5f,-.5f&#41;.normalizeLocal&#40;&#41;&#41;;
110 rootNode.addLight&#40;sun&#41;;</pre>
111
112 </div>
113 <!-- EDIT4 SECTION "DirectionalLight" [2763-3367] -->
114 <h3><a>SpotLight</a></h3>
115 <div>
116
117 <p>
118
119 <img src="nbdocs:/com/jme3/gde/docs/jme3/advanced/spotlight.png">
120 </p>
121
122 <p>
123 A SpotLight sends out a distinct beam or cone of light. A SpotLight has a direction, a position, distance (range) and two angles. The inner angle is the central maximum of the light cone, the outer angle the edge of the light cone. Everything outside the light cone&#039;s angles is not affected by the light.
124 </p>
125
126 <p>
127 <strong>Typical Example:</strong> Flashlight
128 </p>
129 <pre>SpotLight spot = new SpotLight&#40;&#41;;
130 spot.setSpotRange&#40;100f&#41;;                           // distance
131 spot.setSpotInnerAngle&#40;15f * FastMath.DEG_TO_RAD&#41;; // inner light cone (central beam)
132 spot.setSpotOuterAngle&#40;35f * FastMath.DEG_TO_RAD&#41;; // outer light cone (edge of the light)
133 spot.setColor&#40;ColorRGBA.White.mult&#40;1.3f&#41;&#41;;         // light color
134 spot.setPosition&#40;cam.getLocation&#40;&#41;&#41;;               // shine from camera loc
135 spot.setDirection&#40;cam.getDirection&#40;&#41;&#41;;             // shine forward from camera loc
136 rootNode.addLight&#40;spot&#41;;</pre>
137
138 <p>
139 If you want the spotlight to follow the flycam, repeat the setDirection(???) and setPosition(???) calls in the update loop, and kee syncing them with the camera position and direction.
140 </p>
141
142 </div>
143 <!-- EDIT5 SECTION "SpotLight" [3368-4502] -->
144 <h3><a>AmbientLight</a></h3>
145 <div>
146
147 <p>
148
149 An AmbientLight simply influences the brightness and color of the scene globally. It has no direction and no location and shines equally everywhere. An AmbientLight does not cast any shadows, and it lights all sides of Geometries evenly, which makes 3D objects look unnaturally flat; this is why you typically do not use an AmbientLight alone without one of the other lights.  
150 </p>
151
152 <p>
153 <strong>Typical example:</strong> Regulate overall brightness, tinge the whole scene in a warm or cold color. 
154 </p>
155 <pre>AmbientLight al = new AmbientLight&#40;&#41;;
156 al.setColor&#40;ColorRGBA.White.mult&#40;1.3f&#41;&#41;;
157 rootNode.addLight&#40;al&#41;;</pre>
158
159 <p>
160 <p><div>You can increase the brightness of a light source gradually by multiplying the light color to values greater than 1.0f. <br/>
161 Example: <code>mylight.setColor(ColorRGBA.White.mult(1.3f));</code>
162 </div></p>
163 </p>
164
165 </div>
166 <!-- EDIT6 SECTION "AmbientLight" [4503-5325] -->
167 <h2><a>Light Follows Spatial</a></h2>
168 <div>
169
170 <p>
171
172 You can use a <code>com.jme3.scene.control.LightControl</code> to make a SpotLight or PointLight follow a Spatial. This can be used for a flashlight being carried by a character, or for car headlights, or an aircraft&#039;s spotlight, etc.
173 </p>
174 <pre>PointLight myLight = new PointLight&#40;&#41;;
175 rootNode.addLight&#40;myLight&#41;;
176 LightControl lightControl = new LightControl&#40;myLight&#41;;
177 spatial.addControl&#40;lightControl&#41;; // this spatial controls the position of this light.</pre>
178
179 <p>
180 Obviously, this does not apply to AmbientLights, which have no position.
181 </p>
182
183 </div>
184 <!-- EDIT7 SECTION "Light Follows Spatial" [5326-5891] -->
185 <h2><a>Simple Lighting</a></h2>
186 <div>
187
188 <p>
189
190 Full sample code:
191 </p>
192 <ul>
193 <li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestSimpleLighting.java"><param name="text" value="<html><u>TestSimpleLighting.java</u></html>"><param name="textColor" value="blue"></object></div>
194 </li>
195 <li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestLightRadius.java"><param name="text" value="<html><u>TestLightRadius.java</u></html>"><param name="textColor" value="blue"></object></div>
196 </li>
197 </ul>
198
199 <p>
200
201 For Simple Lighting we use Geometries with Materials based on Lighting.j3md (learn <a href="/com/jme3/gde/docs/jme3/advanced/materials_overview.html">more about Materials</a> here). Lighting.j3md-based materials dynamically support Shininess, and Ambient, Diffuse, and Specular light if there is a light source present. Note that this lighting method alone does not make the Geometry cast a shadow onto other Geometries automatically (see below for how to add drop shadows etc).
202 </p>
203
204 <p>
205 <img src="nbdocs:/com/jme3/gde/docs/jme3/advanced/teapot-phong-illuminated.png">
206 </p>
207 <pre>Geometry teapot = &#40;Geometry&#41; assetManager.loadModel&#40;&quot;Models/Teapot/Teapot.obj&quot;&#41;;
208 TangentBinormalGenerator.generate&#40;teapot.getMesh&#40;&#41;, true&#41;;
209 Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Light/Lighting.j3md&quot;&#41;;
210 mat.setBoolean&#40;&quot;m_UseMaterialColors&quot;, true&#41;;
211 mat.setColor&#40;&quot;m_Ambient&quot;,  ColorRGBA.Orange&#41;;
212 mat.setColor&#40;&quot;m_Diffuse&quot;,  ColorRGBA.Orange&#41;;
213 mat.setColor&#40;&quot;m_Specular&quot;, ColorRGBA.White&#41;;
214 mat.setFloat&#40;&quot;m_Shininess&quot;, 12&#41;;
215 rootNode.attachChild&#40;teapot&#41;;</pre>
216
217 <p>
218 The above example uses material colors and no textures. You can of course also use Lighting.j3md to create a lit Material that uses Texture Maps. The following example uses Shininess, Diffuse Map and Normal Map (a.k.a Bump Map).
219 </p>
220
221 <p>
222 <img src="nbdocs:/com/jme3/gde/docs/jme3/advanced/bump-mapped-sphere.png">
223 </p>
224 <pre>Sphere rock = new Sphere&#40;32,32, 2f&#41;;
225 Geometry shiny_rock = new Geometry&#40;&quot;Shiny rock&quot;, rock&#41;;
226 rock.setTextureMode&#40;Sphere.TextureMode.Projected&#41;; // better quality on spheres
227 TangentBinormalGenerator.generate&#40;rock&#41;;           // for lighting effect
228 Material mat_lit = new Material&#40;
229     assetManager, &quot;Common/MatDefs/Light/Lighting.j3md&quot;&#41;;
230 mat_lit.setTexture&#40;&quot;m_DiffuseMap&quot;,                 // surface color
231     assetManager.loadTexture&#40;&quot;Textures/Terrain/Pond/Pond.png&quot;&#41;&#41;;
232 mat_lit.setTexture&#40;&quot;m_NormalMap&quot;,                  // surface bumps
233     assetManager.loadTexture&#40;&quot;Textures/Terrain/Pond/Pond_normal.png&quot;&#41;&#41;;
234 mat_lit.setFloat&#40;&quot;m_Shininess&quot;, 5f&#41;;               // surface smoothness [1,128]
235 shiny_rock.setMaterial&#40;mat_lit&#41;;
236 rootNode.attachChild&#40;shiny_rock&#41;;</pre>
237
238 <p>
239 These light effects update live when the object or light source moves. If you shine a colored PointLight at this object, you will see a light reflection tinged in the color of the PointLight.
240 </p>
241
242 </div>
243 <!-- EDIT8 SECTION "Simple Lighting" [5892-8541] -->
244 <h2><a>BasicShadowRenderer</a></h2>
245 <div>
246
247 <p>
248
249 Full code sample
250 </p>
251 <ul>
252 <li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestShadow.java"><param name="text" value="<html><u>TestShadow.java</u></html>"><param name="textColor" value="blue"></object></div>
253 </li>
254 </ul>
255
256 <p>
257
258 Use the Shadow Renderer to make Geometries with Lighting.j3md-based Materials cast and receive basic drop shadows. This fast and simple implementation of a shadow effect is good for scenes with flat floors, but looks less realistic on uneven terrains. To use it, you add a jME SceneProcessor named com.jme3.shadow.BasicShadowRenderer to the viewPort.
259 </p>
260
261 <p>
262 <img src="nbdocs:/com/jme3/gde/docs/jme3/advanced/drop-shadows.png">
263 </p>
264 <pre>BasicShadowRenderer bsr;
265 ...
266 public void simpleInitApp&#40;&#41; &#123;
267     ...
268     bsr = new BasicShadowRenderer&#40;assetManager, 256&#41;;
269     bsr.setDirection&#40;new Vector3f&#40;-.5f,-.5f,-.5f&#41;.normalizeLocal&#40;&#41;&#41;; // light direction
270     viewPort.addProcessor&#40;bsr&#41;;
271     ...</pre>
272
273 <p>
274 Shadow calculations (cast and receive) have a performance impact, therefor we recommend to use them smartly. Switch off the default shadow mode for the whole scene graph, and then specify the shadow behaviour individually for every scene node that needs shadows: You specifiy whether it casts shadows, receives shadows, both (slower), or neither (faster). 
275 </p>
276 <pre>rootNode.setShadowMode&#40;ShadowMode.Off&#41;;        // reset all
277 wall.setShadowMode&#40;ShadowMode.CastAndReceive&#41;; // normal behaviour (slow)
278 floor.setShadowMode&#40;ShadowMode.Receive&#41;;       // can't see shadow cast below floor anyway...
279 airplane.setShadowMode&#40;ShadowMode.Cast&#41;;       // nothing casts shadows onto airplane anyway...
280 ghost.setShadowMode&#40;ShadowMode.Off&#41;;           // ghost is translucent anyway...</pre>
281
282 </div>
283 <!-- EDIT9 SECTION "BasicShadowRenderer" [8542-10211] -->
284 <h2><a>DirectionalLightShadowRenderer</a></h2>
285 <div>
286
287 <p>
288
289 Full sample code
290 </p>
291 <ul>
292 <li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestDirectionalLightShadow.java"><param name="text" value="<html><u>TestDirectionalLightShadow.java</u></html>"><param name="textColor" value="blue"></object></div>
293 </li>
294 </ul>
295 <pre>        DirectionalLight sun = new DirectionalLight&#40;&#41;;
296         sun.setColor&#40;ColorRGBA.White&#41;;
297         sun.setDirection&#40;cam.getDirection&#40;&#41;&#41;;
298         rootNode.addLight&#40;sun&#41;;
299 &nbsp;
300         /* Drop shadows */
301         final int SHADOWMAP_SIZE=1024;
302         DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer&#40;assetManager, SHADOWMAP_SIZE, 3&#41;;
303         dlsr.setLight&#40;sun&#41;;
304         viewPort.addProcessor&#40;dlsr&#41;;
305 &nbsp;
306         DirectionalLightShadowFilter dlsf = new DirectionalLightShadowFilter&#40;assetManager, SHADOWMAP_SIZE, 3&#41;;
307         dlsf.setLight&#40;sun&#41;;
308         dlsf.setEnabled&#40;true&#41;;
309         FilterPostProcessor fpp = new FilterPostProcessor&#40;assetManager&#41;;
310         fpp.addFilter&#40;dlsf&#41;;
311         viewPort.addProcessor&#40;fpp&#41;;</pre>
312
313 </div>
314 <!-- EDIT10 SECTION "DirectionalLightShadowRenderer" [10212-11184] -->
315 <h2><a>Parallel-Split Shadow Map (deprecated)</a></h2>
316 <div>
317
318 <p>
319
320 Full sample code
321 </p>
322 <ul>
323 <li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestPssmShadow.java"><param name="text" value="<html><u>TestPssmShadow.java</u></html>"><param name="textColor" value="blue"></object></div>
324 </li>
325 </ul>
326
327 <p>
328
329 The more advanced PSSM shadow renderer can cast real-time shadows, even on curved surfaces such as terrains. It is a bit more resource hungry than the BasicShadowRenderer. To activate PSSM drop shadows, add a jME SceneProcessor named <code>com.jme3.shadow.PssmShadowRenderer</code> to the viewPort. PSSM stands for the Parallel-Split Shadow Map technique.
330 </p>
331
332 <p>
333 <img src="nbdocs:/com/jme3/gde/docs/jme3/advanced/shadow.png">
334 </p>
335 <pre>private PssmShadowRenderer pssmRenderer;
336 ...
337 public void simpleInitApp&#40;&#41; &#123;
338     ....
339     pssmRenderer = new PssmShadowRenderer&#40;assetManager, 1024, 3&#41;;
340     pssmRenderer.setDirection&#40;new Vector3f&#40;-.5f,-.5f,-.5f&#41;.normalizeLocal&#40;&#41;&#41;; // light direction
341     viewPort.addProcessor&#40;pssmRenderer&#41;;</pre>
342
343 <p>
344 The constructor expects the following values:
345 </p>
346 <ul>
347 <li><div> Your assetManager object</div>
348 </li>
349 <li><div> The size of the rendered shadowmaps (512, 1024, 2048, etc???)</div>
350 </li>
351 <li><div> The number of shadow maps rendered (the more shadow maps, the more quality, the less FPS).</div>
352 </li>
353 </ul>
354
355 <p>
356
357 You can set the following properties on the <code>pssmRenderer</code> object:
358 </p>
359 <ul>
360 <li><div> setDirection(Vector3f) ??? the direction of the light</div>
361 </li>
362 <li><div> setLambda(0.65f) ??? Factor to use to reduce the split size</div>
363 </li>
364 <li><div> setShadowIntensity(0.7f) ??? shadow darkness (1 black, 0 invisible)</div>
365 </li>
366 <li><div> setShadowZextend() ??? distance how far away from camera shadows will still be computed</div>
367 </li>
368 </ul>
369
370 <p>
371
372 As said above, it&#039;s more efficient to specify individual shadow behaviour for each Geometry.
373 </p>
374 <pre>teapot.setShadowMode&#40;ShadowMode.CastAndReceive&#41;;
375 terrain.setShadowMode&#40;ShadowMode.Receive&#41;; </pre>
376
377 </div>
378 <!-- EDIT11 SECTION "Parallel-Split Shadow Map (deprecated)" [11185-12920] -->
379 <h2><a>Screen Space Ambient Occlusion</a></h2>
380 <div>
381
382 <p>
383
384 Full sample code
385 </p>
386 <ul>
387 <li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestSSAO.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestSSAO.java</u></html>"><param name="textColor" value="blue"></object>, <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestSSAO2.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestSSAO2.java</u></html>"><param name="textColor" value="blue"></object> ??? Screen-Space Ambient Occlusion shadows</div>
388 </li>
389 <li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestTransparentSSAO.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestTransparentSSAO.java</u></html>"><param name="textColor" value="blue"></object> ??? Screen-Space Ambient Occlusion shadows plus transparancy</div>
390 </li>
391 <li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/2010/08/16/screen-space-ambient-occlusion-for-jmonkeyengine-3-0/#more-321"><param name="text" value="<html><u>Screen Space Ambient Occlusion for jMonkeyEngine (article)</u></html>"><param name="textColor" value="blue"></object></div>
392 </li>
393 </ul>
394
395 <p>
396
397 Ambient Occlusion refers to the shadows that nearby objects cast on each other under an ambient lighting. It???s an approximation of how light radiates in a real life scene. To activate Ambient Occlusion shadows, add a jME SceneProcessor named <code>com.jme3.post.SSAOFilter</code> to the viewPort. SSAO stands for the Screen Space Ambient Occlusion technique.
398 </p>
399 <pre>FilterPostProcessor fpp = new FilterPostProcessor&#40;assetManager&#41;;
400 SSAOFilter ssaoFilter = new SSAOFilter&#40;12.94f, 43.92f, 0.33f, 0.61f&#41;;
401 fpp.addFilter&#40;ssaoFilter&#41;;
402 viewPort.addProcessor&#40;fpp&#41;;</pre>
403
404 <p>
405 <img src="nbdocs:/com/jme3/gde/docs/jme3/advanced/shading-textured-ani.gif">
406
407 </p>
408
409 </div>
410 <!-- EDIT12 SECTION "Screen Space Ambient Occlusion" [12921-] -->
411 <p><em><a href="http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:light_and_shadow?do=export_xhtmlbody">view online version</a></em></p>