3D Surface Lighting in Python/v3

How to add lighting effects in 3D Python Plots


Note: this page is part of the documentation for version 3 of Plotly.py, which is not the most recent version.
See our Version 4 Migration Guide for information about how to upgrade.

New to Plotly?

Plotly's Python library is free and open source! Get started by downloading the client and reading the primer.
You can set up Plotly to work in online or offline mode, or in jupyter notebooks.
We also have a quick-reference cheatsheet (new!) to help you get started!

Lighting effects on 3D Surface Plot

In this tutorial, we will generate a simple surface plot, and add various lighting effects to it.

In [1]:
import plotly.plotly as py
import plotly.graph_objs as go
import plotly.tools as tls
import numpy as np
In [2]:
x = np.linspace(-np.pi, np.pi, 100)
y = np.linspace(-np.pi, np.pi, 100)

Y, X = np.meshgrid(x, y)
In [3]:
Z1 = np.cos(X)*np.sin(Y)
Z2 = 2 + np.cos(X)*np.sin(Y)
In [4]:
trace1 = go.Surface(z=Z1, colorscale='Viridis')
In [5]:
py.iplot([trace1])
Out[5]:

There are four lighting effects available in Plotly: ambient, diffuse, roughness, specular, and fresnel. Now, we will add some lightning effects to the above trace, one by one and see their effects:

Ambient

Ambient stands for the default light in the room. We can set it in a range from 0 to 1. If we set it to zero, the trace appears dark. The default Ambient value for plot is 0.8.

In [6]:
fig = tls.make_subplots(rows=1, cols=2,specs=[[{'is_3d': True},{'is_3d': True} ]])


trace1 = go.Surface(z=Z1, colorscale='Viridis', lighting=dict(ambient=0.2))
trace2 = go.Surface(z=Z2, colorscale='Viridis',showscale=False, lighting=dict(ambient=0.9))

fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 1, 2)

py.iplot(fig)
This is the format of your plot grid:
[ (1,1) scene1 ]  [ (1,2) scene2 ]

Out[6]:

Roughness

Roughness in a lighting plot refers to amount of light scattered. The value of roughness can range from 0 to 1 (by default value is 0.5).

In [7]:
fig = tls.make_subplots(rows=1, cols=2,specs=[[{'is_3d': True},{'is_3d': True} ]])
trace1 = go.Surface(z=Z1, colorscale='Viridis', lighting=dict(roughness=0.1))
trace2 = go.Surface(z=Z2, colorscale='Viridis',showscale=False, lighting=dict(roughness=0.9))

fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 1, 2)
py.iplot(fig)
This is the format of your plot grid:
[ (1,1) scene1 ]  [ (1,2) scene2 ]

Out[7]:

Diffuse

By using Diffuse the light is reflected at many angles rather than just one angle. The value ranges from 0 to 1 (default value is 0.8).

In [8]:
fig = tls.make_subplots(rows=1, cols=2,specs=[[{'is_3d': True},{'is_3d': True} ]])
trace1 = go.Surface(z=Z1, colorscale='Viridis', lighting=dict(diffuse=0.1))
trace2 = go.Surface(z=Z2, colorscale='Viridis',showscale=False,lighting=dict(diffuse=0.9))

fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 1, 2)
py.iplot(fig)
This is the format of your plot grid:
[ (1,1) scene1 ]  [ (1,2) scene2 ]

Out[8]:

Fresnel

Fresnel attribute is used to wash light over area of plot. The value can range from 0 to 5 (default value is 0.2).

In [9]:
fig = tls.make_subplots(rows=1, cols=2,specs=[[{'is_3d': True},{'is_3d': True} ]])
trace1 = go.Surface(z=Z1, colorscale='Viridis', lighting=dict(fresnel=0.1))
trace2 = go.Surface(z=Z2, colorscale='Viridis',showscale=False, lighting=dict(fresnel=4.5))

fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 1, 2)
This is the format of your plot grid:
[ (1,1) scene1 ]  [ (1,2) scene2 ]

In [10]:
py.iplot(fig)
Out[10]:

Specular

Specular attribute induces bright spots of lighting in your plot. It's value range from 0 to 2 (default value is 0.05).

In [11]:
fig = tls.make_subplots(rows=1, cols=2,specs=[[{'is_3d': True},{'is_3d': True} ]])
trace1 = go.Surface(z=Z1, colorscale='Viridis', lighting=dict(specular=0.2))
trace2 = go.Surface(z=Z2, colorscale='Viridis',showscale=False ,lighting=dict(specular=2))

fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 1, 2)
py.iplot(fig)
This is the format of your plot grid:
[ (1,1) scene1 ]  [ (1,2) scene2 ]

Out[11]:

Combined effects:

The effects can also be added in a combined manner as follows:

In [12]:
lighting_effects = dict(ambient=0.4, diffuse=0.5, roughness = 0.9, specular=0.6, fresnel=0.2)
trace = go.Surface(z=Z1, colorscale='Viridis', lighting=lighting_effects)

py.iplot([trace])
Out[12]:

Reference

See https://plotly.com/python/reference/#surface-lighting for more information!