Skip to content

Commit 07061c8

Browse files
authored
Merge pull request #123 from vidartf/shadows
Enable shadows, antialias and other renderer config
2 parents 46685c6 + 64b5793 commit 07061c8

24 files changed

+943
-253
lines changed

examples/Shadows.ipynb

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
{
2+
"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+
},
21+
{
22+
"cell_type": "code",
23+
"execution_count": null,
24+
"metadata": {},
25+
"outputs": [],
26+
"source": [
27+
"from pythreejs import *\n",
28+
"import ipywidgets\n",
29+
"from IPython.display import display"
30+
]
31+
},
32+
{
33+
"cell_type": "code",
34+
"execution_count": null,
35+
"metadata": {},
36+
"outputs": [],
37+
"source": [
38+
"view_width = 800\n",
39+
"view_height = 600"
40+
]
41+
},
42+
{
43+
"cell_type": "markdown",
44+
"metadata": {},
45+
"source": [
46+
"Create some example geometry in nice coder colors:"
47+
]
48+
},
49+
{
50+
"cell_type": "code",
51+
"execution_count": null,
52+
"metadata": {},
53+
"outputs": [],
54+
"source": [
55+
"sphere = Mesh(\n",
56+
" SphereBufferGeometry(1, 32, 16),\n",
57+
" MeshStandardMaterial(color='red')\n",
58+
")"
59+
]
60+
},
61+
{
62+
"cell_type": "code",
63+
"execution_count": null,
64+
"metadata": {},
65+
"outputs": [],
66+
"source": [
67+
"cube = Mesh(\n",
68+
" BoxBufferGeometry(1, 1, 1),\n",
69+
" MeshPhysicalMaterial(color='green'),\n",
70+
" position=[2, 0, 4]\n",
71+
")"
72+
]
73+
},
74+
{
75+
"cell_type": "code",
76+
"execution_count": null,
77+
"metadata": {},
78+
"outputs": [],
79+
"source": [
80+
"plane = Mesh(\n",
81+
" PlaneBufferGeometry(10, 10),\n",
82+
" MeshPhysicalMaterial(color='gray'),\n",
83+
" position=[0, -2, 0],)\n",
84+
"plane.rotation = (-3.14/2, 0, 0, 'XYZ')"
85+
]
86+
},
87+
{
88+
"cell_type": "markdown",
89+
"metadata": {},
90+
"source": [
91+
"Create camera and lighting:"
92+
]
93+
},
94+
{
95+
"cell_type": "code",
96+
"execution_count": null,
97+
"metadata": {},
98+
"outputs": [],
99+
"source": [
100+
"camera = PerspectiveCamera( position=[10, 6, 10], aspect=view_width/view_height)\n",
101+
"key_light = SpotLight(position=[0, 10, 10], angle = 0.3, penumbra = 0.1)\n",
102+
"ambient_light = AmbientLight()"
103+
]
104+
},
105+
{
106+
"cell_type": "code",
107+
"execution_count": null,
108+
"metadata": {},
109+
"outputs": [],
110+
"source": [
111+
"scene = Scene(children=[sphere, cube, plane, camera, key_light, ambient_light])\n",
112+
"controller = OrbitControls(controlling=camera)\n",
113+
"renderer = Renderer(camera=camera, scene=scene, controls=[controller],\n",
114+
" width=view_width, height=view_height, antialias=True)"
115+
]
116+
},
117+
{
118+
"cell_type": "code",
119+
"execution_count": null,
120+
"metadata": {
121+
"scrolled": false
122+
},
123+
"outputs": [],
124+
"source": [
125+
"renderer"
126+
]
127+
},
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+
},
160+
{
161+
"cell_type": "code",
162+
"execution_count": null,
163+
"metadata": {},
164+
"outputs": [],
165+
"source": [
166+
"renderer.shadowMap.enabled = True\n",
167+
"renderer.shadowMap.type = 'PCFSoftShadowMap' # default PCFShadowMap"
168+
]
169+
},
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+
},
177+
{
178+
"cell_type": "code",
179+
"execution_count": null,
180+
"metadata": {},
181+
"outputs": [],
182+
"source": [
183+
"# Enable shadows for the light\n",
184+
"key_light.castShadow = True\n",
185+
"\n",
186+
"# Enable casting/receiving shadows for some objects:\n",
187+
"sphere.castShadow = True\n",
188+
"cube.castShadow = True\n",
189+
"plane.receiveShadow = True"
190+
]
191+
},
192+
{
193+
"cell_type": "markdown",
194+
"metadata": {},
195+
"source": [
196+
"Let's move the cube closer to the sphere:"
197+
]
198+
},
199+
{
200+
"cell_type": "code",
201+
"execution_count": null,
202+
"metadata": {},
203+
"outputs": [],
204+
"source": [
205+
"cube.position = (0, 1, 2)"
206+
]
207+
},
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+
},
215+
{
216+
"cell_type": "code",
217+
"execution_count": null,
218+
"metadata": {},
219+
"outputs": [],
220+
"source": [
221+
"# Also enable sphere to receive shadow:\n",
222+
"sphere.receiveShadow = True\n",
223+
"sphere.material.needsUpdate = True"
224+
]
225+
},
226+
{
227+
"cell_type": "markdown",
228+
"metadata": {},
229+
"source": [
230+
"Finally, let's zoom in on the details of the shadows:"
231+
]
232+
},
233+
{
234+
"cell_type": "code",
235+
"execution_count": null,
236+
"metadata": {},
237+
"outputs": [],
238+
"source": [
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:"
248+
]
249+
},
250+
{
251+
"cell_type": "code",
252+
"execution_count": null,
253+
"metadata": {},
254+
"outputs": [],
255+
"source": [
256+
"key_light.shadow.mapSize = (2048, 2048)"
257+
]
258+
},
259+
{
260+
"cell_type": "code",
261+
"execution_count": null,
262+
"metadata": {},
263+
"outputs": [],
264+
"source": []
265+
}
266+
],
267+
"metadata": {
268+
"kernelspec": {
269+
"display_name": "Python 3",
270+
"language": "python",
271+
"name": "python3"
272+
},
273+
"language_info": {
274+
"codemirror_mode": {
275+
"name": "ipython",
276+
"version": 3
277+
},
278+
"file_extension": ".py",
279+
"mimetype": "text/x-python",
280+
"name": "python",
281+
"nbconvert_exporter": "python",
282+
"pygments_lexer": "ipython3",
283+
"version": "3.5.4"
284+
}
285+
},
286+
"nbformat": 4,
287+
"nbformat_minor": 2
288+
}

js/scripts/generate-wrappers.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,18 @@ var IGNORE_FILES = [
5959
'**/materials/MeshDistanceMaterial.js', // TODO: Undocumented as of yet
6060
'**/renderers/WebGLRenderer.js', // For now, the internals of the webgl
6161
'**/renderers/WebGL2Renderer.js', // render is not exposed.
62-
'**/renderers/webgl/**',
62+
//'**/renderers/webgl/**',
63+
'**/renderers/webgl/WebGLAttributes.js',
64+
'**/renderers/webgl/WebGLBackground.js',
65+
'**/renderers/webgl/WebGLClipping.js',
66+
'**/renderers/webgl/WebGLFlareRenderer.js',
67+
'**/renderers/webgl/WebGLMorphtargets.js',
68+
'**/renderers/webgl/WebGLRenderLists.js',
69+
'**/renderers/webgl/WebGLSpriteRenderer.js',
70+
'**/renderers/webgl/WebGLTextures.js',
71+
'**/renderers/webgl/WebGLUniforms.js',
72+
'**/renderers/webgl/WebGLUtils.js',
73+
'**/renderers/webvr/**',
6374
'**/renderers/shaders/**',
6475
'**/extras/core/Interpolations.js', // Only functions, nothing to export
6576
'**/extras/core/PathPrototype.js', // Sub-part of one object, ignore
@@ -817,10 +828,6 @@ _.extend(PythonWrapper.prototype, {
817828

818829
var refTokens = this.modulePath.split(pathSep);
819830

820-
// capitalize elements in url
821-
refTokens = refTokens.map(function(token) {
822-
return token.charAt(0).toUpperCase() + token.slice(1);
823-
});
824831
// strip extension off filename
825832
refTokens[refTokens.length - 1] = path.basename(refTokens[refTokens.length - 1], '.js');
826833

0 commit comments

Comments
 (0)