Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Lights and Shadows #308

Open
wants to merge 132 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
2a140da
Test Phong lighting support for plot_mesh. Add lighting_demo notebook.
Mar 17, 2020
29d1d16
Test shadowmap with spotlight. Fix shadow acne.
Mar 19, 2020
55d6b98
Add Lambert lighting model shaders
Mar 19, 2020
88d019f
Add Physical lighting model shaders
Mar 20, 2020
5918a74
Create widgets_test.ipynb
rinftech-github Mar 23, 2020
6cb9964
Update widgets
rinftech-github Mar 25, 2020
5d739f2
Add Light widget classes. Add ambiental_light functionality
Mar 26, 2020
74f2eda
Add directional_light functionality
Mar 26, 2020
e30d1fa
Add hemisphere_light functionality
Mar 26, 2020
0d5f58e
Add spot_light functionality. Add target to directional_light
Mar 27, 2020
b76be11
Add point_light functionality
Mar 27, 2020
69480d3
Updates
rinftech-github Mar 27, 2020
9db5bcf
Add shadowmap support for spot_light
Mar 27, 2020
700c735
[Bugfixes]
rinftech-github Mar 27, 2020
467609d
Add shadowmap support for directional_light
Mar 27, 2020
d4c7d2d
Add shadowmap support for point_light. Add shadow_radius
Mar 27, 2020
2f1478b
Simplify lighting_demo notebook. Replace color with light_color
Mar 29, 2020
fd5e785
Add mesh widget material params. Add shadowmap types. Mesh class cleanup
Mar 29, 2020
b057d00
Propagate material params. Add plot_surface example
Mar 29, 2020
b11a537
Prepare lighting material uniforms for scatter rendering
Mar 29, 2020
2fc6c64
Add Scatter physical shaders
Mar 29, 2020
0eea214
Scatter lighting shaders work in progress - InstancedBufferGeometry s…
Mar 30, 2020
db927ee
Finished notebook lighting demo for plot_mesh, plot_trisurf and plot_…
Mar 30, 2020
56657e7
Fix notebook figure autoupdate. Hardcode lambert and phong diffuse co…
Mar 31, 2020
b7da181
Prepare notebook for plot_mesh material properties change
Mar 31, 2020
b77d204
Switch lighting model automatically to PHYSICAL when adding a new light
Mar 31, 2020
66bc1de
Complete mesh and lighting demo notebook. Fix Lambert emissive intens…
Mar 31, 2020
1b71716
Replace radius with shadow_radius in demo notebook
Mar 31, 2020
f2c6c38
Switch scatter lighting model to PHYSICAL when adding a light. Scatte…
Mar 31, 2020
c0bafd6
Update lighting demo notebook
Mar 31, 2020
1212c8a
Add unit tests. Remove cast_shadow from hemisphere_light
Mar 31, 2020
e1fe838
Add/update function description for plot_mesh, plot_surface, plot_tri…
Apr 1, 2020
d3a8979
Code cleanup
Apr 1, 2020
4978259
Fix shadow_map_size description. Add scatter information about lighti…
Apr 1, 2020
2012bd9
Update unit tests
Apr 1, 2020
fd1c121
Updated lighting demos with animation example
Apr 2, 2020
2ff64a1
Merge all mesh shading models into one vertex and one fragment shader
Jun 29, 2020
554fb99
Remove unnecessary shader files. Remove shader export directives
Jun 29, 2020
659e841
Merge scatter shaders into one vertex and one fragment file. Remove p…
Jul 1, 2020
75e8c77
Remove update_visibility from mesh and scatter. Remove transparent re…
Jul 2, 2020
55099f3
Remove unnecessary computeVertexNormals() call. Add argumentation com…
Jul 2, 2020
2d1a842
Begin removing Light widget
Jul 9, 2020
39ff7f6
Replace emissive_color with color. Adjust default emissive_intensity …
Jul 17, 2020
12b9b4d
lighting_demo notebook UI updates
Jul 23, 2020
235c735
Updated lighting demos with animation example
Apr 2, 2020
358ef8a
begin removing light.ts
Jul 27, 2020
a0eeb5a
add enable_shadows and shadow_map_type to figure.ts, I hope
Jul 27, 2020
f7bcf49
properly merge notebook from fd1c121829c868fa91ebb3a75b670a54a9a92bd6
Jul 27, 2020
8e118fe
cleanup point light
Jul 27, 2020
687e092
fix typo
Jul 27, 2020
13bfaec
really fix typo
Jul 27, 2020
8c63159
add construct light method
Jul 28, 2020
87ce688
dir and spot light seem to work
Jul 28, 2020
966ab9f
not async
Jul 28, 2020
d7f6ffe
attempt to delete previous lights
Jul 28, 2020
5834a91
enable shadows
Jul 28, 2020
caa28a5
test notebook
Jul 28, 2020
d914467
delete lights on re-add
Jul 28, 2020
eba6d62
fix ligthing model for meshes
Jul 28, 2020
c4eb372
cleanup old code
Jul 28, 2020
fd68aed
setup light wapper
Jul 28, 2020
562fe94
attempt at wrapping all light objects
Jul 28, 2020
f414bf3
fix runtime errors
Jul 28, 2020
4dec607
fix inheritance
Jul 28, 2020
9711c39
HemisphereLight typo
Jul 28, 2020
f418d8d
fix typos, update notebook
Jul 28, 2020
a22ab4d
fix notebook
Jul 28, 2020
ffa373c
undo light wrappers
Jul 28, 2020
4d68f43
Add flat_shading option. Improve notebook ui for meshes (lighting_demo)
Jul 28, 2020
8bcbf9f
add wrapper methods and refactor notebook
Jul 29, 2020
e9203c9
finished implemeting light changes update
Jul 29, 2020
bcc01a0
Set shadows cast/received to default True. Improvement to notebook me…
Jul 29, 2020
79d4edd
add target to scene
Jul 29, 2020
9e807d9
wip
Jul 29, 2020
8a883df
update shadows on prop change
Jul 29, 2020
ceecaef
refactor method names
Jul 29, 2020
c44999a
rm todo
Jul 29, 2020
688908c
attempt to hook only needed changes
Jul 29, 2020
ccc9867
hook all the things
Jul 29, 2020
8e5da84
refactor notebook
Jul 29, 2020
4860873
rm console log
Jul 29, 2020
ffe5d54
debug
Jul 29, 2020
421c9cb
Add UI elements for Ambient and Hemisphere lights in light demo notebook
Jul 29, 2020
6c55384
Add ui elements for Directional and Spot Lights in notebook. Remove s…
Jul 29, 2020
8e1f2a4
Add Point Light ui in lighting demo notebook
Jul 29, 2020
ee6c733
Merge branch 'feat_lighting' into feat_lighting_merge
Jul 30, 2020
a654619
rm old notebook
Jul 30, 2020
ce0243d
rm shadow_map_type
Jul 30, 2020
5202b53
start merge
Jul 30, 2020
f71fe10
update widget mesh booleans
Jul 30, 2020
3658c02
forgot to add fields
Jul 30, 2020
35deb4e
no more crashes
Jul 30, 2020
5506daa
Remove target from point light in demo notebook
Jul 30, 2020
60b5afd
watch for child change
Jul 30, 2020
20c349c
fix shadow binding
Jul 30, 2020
9548bed
latest notebook
Jul 30, 2020
707f433
add todo
Jul 30, 2020
2babe15
minor refactor
Jul 30, 2020
8692d07
add note about error
Jul 30, 2020
ab6651e
Remove show_material_widgets and show_light_widgets from notebook and…
Jul 30, 2020
a2caf32
Add function which parses all lights and meshes from figure and gener…
Jul 30, 2020
0be164f
Update show_lighting_widgets name
Aug 6, 2020
d68d33f
Remove name parameter from setup_material_widgets and setup_light_wid…
Aug 6, 2020
3557798
Replace position and target FloatSlider with FloatText
Aug 6, 2020
63b4b64
Customize light widgets ui layout and style
Aug 6, 2020
d48ba29
Fix incorrect lighting model value in UI
Aug 6, 2020
6b069af
proposed fixed from Marteen for directional light
Aug 7, 2020
c8b3992
fix also sptolight
Aug 7, 2020
ad013ab
fix point light
Aug 7, 2020
2e25a24
Merge branch 'feat_lighting' into feat_ligthing_widget
Aug 7, 2020
fa5386e
update notebok
Aug 7, 2020
13e75c9
fix light type and pos
Aug 7, 2020
1de0414
fix target
Aug 7, 2020
3fddedb
castShadow
Aug 7, 2020
cbc474b
fix other params
Aug 7, 2020
1db2655
rm light.ts
Aug 7, 2020
978400f
fix typos
Aug 7, 2020
387845c
fix light_color
Aug 7, 2020
0f1f15a
type name
Aug 7, 2020
d1c088f
fix final
Aug 7, 2020
ff96b4b
rm unused
Aug 7, 2020
7c5f761
fix position
Aug 7, 2020
fcf0be2
Updates to light default param values. Shadowmap fixes
Aug 8, 2020
06e1ac6
Update lighting_demo notebook. Remove shadow_map_type
Aug 8, 2020
3c696ed
Remove emissive_color completely from mesh. Tweak mesh documentation …
Aug 8, 2020
00130c4
Remove completely emissive_color from scatter. Other Directional ligh…
Aug 9, 2020
1e5a79e
Update light unit tests
Aug 9, 2020
69592f1
Fix hemisphere light color set
Aug 9, 2020
6ef4798
Remove scatter fragment flatshading color overwrite. Enable flatshadi…
Aug 9, 2020
e036afb
Extra scatter flatshading set
Aug 10, 2020
a580c9b
Add documentation to widget functions
Aug 10, 2020
48db5a2
Remove wrap_lights
Aug 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion ipyvolume/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from ipyvolume.transferfunction import * # noqa: F401, F403
from ipyvolume.pylab import * # noqa: F401, F403


def _jupyter_nbextension_paths():
return [{
'section': 'notebook',
Expand Down
661 changes: 647 additions & 14 deletions ipyvolume/pylab.py
100644 → 100755

Large diffs are not rendered by default.

138 changes: 138 additions & 0 deletions ipyvolume/test_all.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import shutil
import json
import contextlib
import math

import numpy as np
import pytest
Expand Down Expand Up @@ -449,3 +450,140 @@ def test_datasets():
ipyvolume.datasets.aquariusA2.fetch()
ipyvolume.datasets.hdz2000.fetch()
ipyvolume.datasets.zeldovich.fetch()


def test_mesh_material():
def test_material_components(mesh=None, is_scatter=False):
assert mesh.lighting_model == 'DEFAULT'
assert mesh.opacity == 1
assert mesh.specular_color == 'white'
assert mesh.shininess == 1
assert mesh.color == 'red'
assert mesh.emissive_intensity == 0.2
assert mesh.roughness == 0
assert mesh.metalness == 0
if is_scatter == False:
assert mesh.cast_shadow == True
assert mesh.receive_shadow == True

mesh.lighting_model = 'PHYSICAL'
mesh.opacity = 0
mesh.specular_color = 'blue'
mesh.shininess = 10
mesh.color = 'red'
mesh.emissive_intensity = 2
mesh.roughness = 1
mesh.metalness = 5
if is_scatter == False:
mesh.cast_shadow = True
mesh.receive_shadow = True

assert mesh.lighting_model == 'PHYSICAL'
assert mesh.opacity == 0
assert mesh.specular_color == 'blue'
assert mesh.shininess == 10
assert mesh.color == 'red'
assert mesh.emissive_intensity == 2
assert mesh.roughness == 1
assert mesh.metalness == 5
if is_scatter == False:
assert mesh.cast_shadow == True
assert mesh.receive_shadow == True

x, y, z, u, v = ipyvolume.examples.klein_bottle(draw=False)

ipyvolume.figure()
mesh = ipyvolume.plot_mesh( x, y, z)
test_material_components(mesh)

k = 20
h = -15
tx = np.array([k, -k, -k, k])
tz = np.array([k, k, -k, -k])
ty = np.array([h, h, h, h])

tri = [(0, 1, 2), (0, 2, 3)]
trisurf = ipyvolume.plot_trisurf(tx, ty, tz, triangles=tri)
test_material_components(trisurf)

X = np.arange(-10, 10, 0.25*1)-10
Y = np.arange(-10, 10, 0.25*1)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)

surf = ipyvolume.plot_surface(X, Z, Y)
test_material_components(surf)

x, y, z = np.random.random((3, 10000))
scatter = ipyvolume.scatter(x, y, z, size=1, marker="sphere")
test_material_components(scatter, True)


def test_light_components():
ambient = ipyvolume.ambient_light()
assert ambient.type == 'AmbientLight'
assert ambient.color == 'white'
assert ambient.intensity == 1

hemisphere = ipyvolume.hemisphere_light()
assert hemisphere.type == 'HemisphereLight'
assert hemisphere.color == '#ffffff'
assert hemisphere.groundColor == 'red'
assert hemisphere.intensity == 1
assert hemisphere.position[0] == 0
assert hemisphere.position[1] == 1
assert hemisphere.position[2] == 0

directional = ipyvolume.directional_light()
assert directional.color == 'white'
assert directional.intensity == 1
assert directional.position[0] == 10
assert directional.position[1] == 10
assert directional.position[2] == 10
assert directional.target.position[0] == 0
assert directional.target.position[1] == 0
assert directional.target.position[2] == 0
assert directional.castShadow==True
assert directional.shadow.bias==-0.0008
assert directional.shadow.radius==1
assert directional.shadow.camera.near==0.5
assert directional.shadow.camera.far==5000
assert directional.shadow.mapSize[0]==1024
assert directional.shadow.camera.left==-256/2
assert directional.shadow.camera.right==256/2
assert directional.shadow.camera.top==256/2
assert directional.shadow.camera.bottom==-256/2

spot = ipyvolume.spot_light()
assert spot.color == 'white'
assert spot.intensity == 1
assert spot.position[0] == 10
assert spot.position[1] == 10
assert spot.position[2] == 10
assert spot.target.position[0] == 0
assert spot.target.position[1] == 0
assert spot.target.position[2] == 0
assert spot.shadow.camera.fov==90
assert spot.castShadow==True
assert spot.shadow.mapSize[0]==1024
assert spot.shadow.bias==-0.0008
assert spot.shadow.radius==1
assert spot.shadow.camera.near==0.5
assert spot.shadow.camera.far==5000

point = ipyvolume.point_light()
assert point.color == 'white'
assert point.intensity == 1
assert point.position[0] == 10
assert point.position[1] == 10
assert point.position[2] == 10
assert point.shadow.camera.fov==90
assert point.castShadow==True
assert point.distance==0
assert point.decay==1
assert point.shadow.mapSize[0]==1024
assert point.shadow.bias==-0.0008
assert point.shadow.radius==1
assert point.shadow.camera.near==0.5
assert point.shadow.camera.far==5000
35 changes: 32 additions & 3 deletions ipyvolume/widgets.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
)
from ipyvolume.transferfunction import TransferFunction
from ipyvolume.utils import debounced, grid_slice, reduce_size

import math

_last_figure = None
logger = logging.getLogger("ipyvolume")
Expand Down Expand Up @@ -64,6 +64,17 @@ class Mesh(widgets.Widget):
color = Array(default_value="red", allow_none=True).tag(sync=True, **color_serialization)
visible = traitlets.CBool(default_value=True).tag(sync=True)

lighting_model = traitlets.Enum(values=['DEFAULT', 'LAMBERT', 'PHONG', 'PHYSICAL'], default_value='DEFAULT').tag(sync=True)
opacity = traitlets.CFloat(1).tag(sync=True)
emissive_intensity = traitlets.CFloat(1).tag(sync=True)
specular_color = Array(default_value="white", allow_none=True).tag(sync=True, **color_serialization)
shininess = traitlets.CFloat(1).tag(sync=True)
roughness = traitlets.CFloat(0).tag(sync=True)
metalness = traitlets.CFloat(0).tag(sync=True)
cast_shadow = traitlets.CBool(default_value=True).tag(sync=True)
receive_shadow = traitlets.CBool(default_value=True).tag(sync=True)
flat_shading = traitlets.CBool(default_value=True).tag(sync=True)

material = traitlets.Instance(
pythreejs.ShaderMaterial, help='A :any:`pythreejs.ShaderMaterial` that is used for the mesh'
).tag(sync=True, **widgets.widget_serialization)
Expand All @@ -80,7 +91,6 @@ def _default_material(self):
def _default_line_material(self):
return pythreejs.ShaderMaterial()


@widgets.register
class Scatter(widgets.Widget):
_view_name = Unicode('ScatterView').tag(sync=True)
Expand Down Expand Up @@ -120,6 +130,16 @@ class Scatter(widgets.Widget):
connected = traitlets.CBool(default_value=False).tag(sync=True)
visible = traitlets.CBool(default_value=True).tag(sync=True)

lighting_model = traitlets.Enum(values=['DEFAULT', 'PHYSICAL'], default_value='DEFAULT').tag(sync=True)
opacity = traitlets.CFloat(1).tag(sync=True)
specular_color = Array(default_value="white", allow_none=True).tag(sync=True, **color_serialization)
shininess = traitlets.CFloat(1).tag(sync=True)
emissive_intensity = traitlets.CFloat(1).tag(sync=True)
roughness = traitlets.CFloat(0).tag(sync=True)
metalness = traitlets.CFloat(0).tag(sync=True)
cast_shadow = traitlets.CBool(default_value=False).tag(sync=True)
receive_shadow = traitlets.CBool(default_value=False).tag(sync=True)

texture = traitlets.Union(
[
traitlets.Instance(ipywebrtc.MediaStream),
Expand Down Expand Up @@ -217,7 +237,7 @@ def _update_data(self):
self.data = np.array(data_view)
self.extent = extent


@widgets.register
class Figure(ipywebrtc.MediaStream):
"""Widget class representing a volume (rendering) using three.js."""
Expand All @@ -240,6 +260,13 @@ class Figure(ipywebrtc.MediaStream):
volumes = traitlets.List(traitlets.Instance(Volume), [], allow_none=False).tag(
sync=True, **widgets.widget_serialization
)

#lights = traitlets.List(traitlets.Instance(Light), [], allow_none=False).tag(
# sync=True, **widgets.widget_serialization
#)
lights = traitlets.List(traitlets.Instance(pythreejs.Light), [], allow_none=False).tag(
sync=True, **widgets.widget_serialization
)

animation = traitlets.Float(1000.0).tag(sync=True)
animation_exponent = traitlets.Float(1.0).tag(sync=True)
Expand All @@ -260,6 +287,8 @@ class Figure(ipywebrtc.MediaStream):
pythreejs.Camera, allow_none=True, help='A :any:`pythreejs.Camera` instance to control the camera'
).tag(sync=True, **widgets.widget_serialization)

enable_shadows = traitlets.Bool(False).tag(sync=True)

@traitlets.default('camera')
def _default_camera(self):
# see https://github.com/maartenbreddels/ipyvolume/pull/40 for an explanation
Expand Down
Loading