Skip to content

Commit 64b5793

Browse files
committed
Complete shadow examples notebook
1 parent 397d5a4 commit 64b5793

File tree

1 file changed

+107
-6
lines changed

1 file changed

+107
-6
lines changed

examples/Shadows.ipynb

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
{
22
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Shadows with pythreejs\n",
8+
"\n",
9+
"This example is meant to demonstrate how to set up shadows with pythreejs. It is mainly based on the example code you can find in the three.js documentation, but is adapted to highlight some of the nuances of using it from pythreejs."
10+
]
11+
},
12+
{
13+
"cell_type": "markdown",
14+
"metadata": {},
15+
"source": [
16+
"## Setup\n",
17+
"\n",
18+
"First, we set up an example scene for exploring shadow behavior."
19+
]
20+
},
321
{
422
"cell_type": "code",
523
"execution_count": null,
@@ -21,6 +39,13 @@
2139
"view_height = 600"
2240
]
2341
},
42+
{
43+
"cell_type": "markdown",
44+
"metadata": {},
45+
"source": [
46+
"Create some example geometry in nice coder colors:"
47+
]
48+
},
2449
{
2550
"cell_type": "code",
2651
"execution_count": null,
@@ -59,6 +84,13 @@
5984
"plane.rotation = (-3.14/2, 0, 0, 'XYZ')"
6085
]
6186
},
87+
{
88+
"cell_type": "markdown",
89+
"metadata": {},
90+
"source": [
91+
"Create camera and lighting:"
92+
]
93+
},
6294
{
6395
"cell_type": "code",
6496
"execution_count": null,
@@ -67,7 +99,6 @@
6799
"source": [
68100
"camera = PerspectiveCamera( position=[10, 6, 10], aspect=view_width/view_height)\n",
69101
"key_light = SpotLight(position=[0, 10, 10], angle = 0.3, penumbra = 0.1)\n",
70-
"key_light.target = cube\n",
71102
"ambient_light = AmbientLight()"
72103
]
73104
},
@@ -86,23 +117,63 @@
86117
{
87118
"cell_type": "code",
88119
"execution_count": null,
89-
"metadata": {},
120+
"metadata": {
121+
"scrolled": false
122+
},
90123
"outputs": [],
91124
"source": [
92125
"renderer"
93126
]
94127
},
128+
{
129+
"cell_type": "markdown",
130+
"metadata": {},
131+
"source": [
132+
"## Configuring shadows\n",
133+
"\n",
134+
"Now we can start playing around with the shadows in such a way that the results of the different options are immediately shown in the rendered scene."
135+
]
136+
},
137+
{
138+
"cell_type": "markdown",
139+
"metadata": {},
140+
"source": [
141+
"First, set the spot light to track the cube position:"
142+
]
143+
},
144+
{
145+
"cell_type": "code",
146+
"execution_count": null,
147+
"metadata": {},
148+
"outputs": [],
149+
"source": [
150+
"key_light.target = cube"
151+
]
152+
},
153+
{
154+
"cell_type": "markdown",
155+
"metadata": {},
156+
"source": [
157+
"Turn on shadows in the renderer:"
158+
]
159+
},
95160
{
96161
"cell_type": "code",
97162
"execution_count": null,
98163
"metadata": {},
99164
"outputs": [],
100165
"source": [
101-
"# Turn on shadows in the renderer\n",
102166
"renderer.shadowMap.enabled = True\n",
103167
"renderer.shadowMap.type = 'PCFSoftShadowMap' # default PCFShadowMap"
104168
]
105169
},
170+
{
171+
"cell_type": "markdown",
172+
"metadata": {},
173+
"source": [
174+
"Even with shadow maps enabled, there are still no shadows. This is because three.js only includes those lights and objects that has been explicitly marked for shadows in its calculations. Let's turn on some of these:"
175+
]
176+
},
106177
{
107178
"cell_type": "code",
108179
"execution_count": null,
@@ -111,12 +182,20 @@
111182
"source": [
112183
"# Enable shadows for the light\n",
113184
"key_light.castShadow = True\n",
114-
"# Enable objects for casting/receiving shadows:\n",
185+
"\n",
186+
"# Enable casting/receiving shadows for some objects:\n",
115187
"sphere.castShadow = True\n",
116188
"cube.castShadow = True\n",
117189
"plane.receiveShadow = True"
118190
]
119191
},
192+
{
193+
"cell_type": "markdown",
194+
"metadata": {},
195+
"source": [
196+
"Let's move the cube closer to the sphere:"
197+
]
198+
},
120199
{
121200
"cell_type": "code",
122201
"execution_count": null,
@@ -126,6 +205,13 @@
126205
"cube.position = (0, 1, 2)"
127206
]
128207
},
208+
{
209+
"cell_type": "markdown",
210+
"metadata": {},
211+
"source": [
212+
"Note that the light changed to track the position of the cube. It is also clear that the shadow from the cube is not being taken into account on the sphere. As before, we can turn this on with `receiveShadow` on the sphere, but we also need to mark the sphere material for an update. This is needed for any shadow changes *after the first frame with shadows* is rendered."
213+
]
214+
},
129215
{
130216
"cell_type": "code",
131217
"execution_count": null,
@@ -137,13 +223,28 @@
137223
"sphere.material.needsUpdate = True"
138224
]
139225
},
226+
{
227+
"cell_type": "markdown",
228+
"metadata": {},
229+
"source": [
230+
"Finally, let's zoom in on the details of the shadows:"
231+
]
232+
},
140233
{
141234
"cell_type": "code",
142235
"execution_count": null,
143236
"metadata": {},
144237
"outputs": [],
145238
"source": [
146-
"key_light.shadow.mapSize = (2048, 2048)"
239+
"camera.position = [2.92, 1.75, 2.92]\n",
240+
"camera.quaternion = [-0.18, 0.38, 0.076, 0.90]"
241+
]
242+
},
243+
{
244+
"cell_type": "markdown",
245+
"metadata": {},
246+
"source": [
247+
"Here, we can see that there is some pixelation of the shadows (although it is smoothed by using `PCFSoftShadowMap`). This can be fixed by increasing the resolution of the shadow map:"
147248
]
148249
},
149250
{
@@ -152,7 +253,7 @@
152253
"metadata": {},
153254
"outputs": [],
154255
"source": [
155-
"repr(key_light.shadow.camera)"
256+
"key_light.shadow.mapSize = (2048, 2048)"
156257
]
157258
},
158259
{

0 commit comments

Comments
 (0)