Skip to content

Shadows

vtk-examples/Python/Rendering/Shadows

Other languages

See (Cxx)

Question

If you have a question about this example, please use the VTK Discourse Forum

Code

Shadows.py

#!/usr/bin/env python

# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkFiltersSources import (
    vtkCubeSource,
    vtkSphereSource
)
from vtkmodules.vtkIOGeometry import (
    vtkBYUReader,
    vtkOBJReader,
    vtkSTLReader
)
from vtkmodules.vtkIOPLY import vtkPLYReader
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkLight,
    vtkPolyDataMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer
)
from vtkmodules.vtkRenderingOpenGL2 import (
    vtkCameraPass,
    vtkRenderPassCollection,
    vtkSequencePass,
    vtkShadowMapPass
)


def get_program_parameters():
    import argparse
    description = 'Read a polydata file of a surface and display it with shadows.'
    epilogue = '''
If no file is entered a sphere is used.
   '''
    parser = argparse.ArgumentParser(description=description, epilog=epilogue,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('filename', default=None, nargs='?', help='Enter a polydata file e.g cow.g.')
    args = parser.parse_args()
    return args.filename


def ReadPolyData(file_name):
    import os
    path, extension = os.path.splitext(file_name)
    extension = extension.lower()
    if extension == '.ply':
        reader = vtkPLYReader()
        reader.SetFileName(file_name)
        reader.Update()
        poly_data = reader.GetOutput()
    elif extension == '.vtp':
        reader = vtkXMLpoly_dataReader()
        reader.SetFileName(file_name)
        reader.Update()
        poly_data = reader.GetOutput()
    elif extension == '.obj':
        reader = vtkOBJReader()
        reader.SetFileName(file_name)
        reader.Update()
        poly_data = reader.GetOutput()
    elif extension == '.stl':
        reader = vtkSTLReader()
        reader.SetFileName(file_name)
        reader.Update()
        poly_data = reader.GetOutput()
    elif extension == '.vtk':
        reader = vtkpoly_dataReader()
        reader.SetFileName(file_name)
        reader.Update()
        poly_data = reader.GetOutput()
    elif extension == '.g':
        reader = vtkBYUReader()
        reader.SetGeometryFileName(file_name)
        reader.Update()
        poly_data = reader.GetOutput()
    else:
        # Return a None if the extension is unknown.
        poly_data = None
    return poly_data


def main():
    fn = get_program_parameters()
    if fn:
        polyData = ReadPolyData(fn)
    else:
        # Use a sphere
        source = vtkSphereSource()
        source.SetThetaResolution(100)
        source.SetPhiResolution(100)
        source.Update()
        polyData = source.GetOutput()

    colors = vtkNamedColors()
    colors.SetColor('HighNoonSun', [255, 255, 251, 255])  # Color temp. 5400°K
    colors.SetColor('100W Tungsten', [255, 214, 170, 255])  # Color temp. 2850°K

    renderer = vtkRenderer()
    renderer.SetBackground(colors.GetColor3d('Silver'))

    renderWindow = vtkRenderWindow()
    renderWindow.SetSize(640, 480)
    renderWindow.AddRenderer(renderer)

    interactor = vtkRenderWindowInteractor()
    interactor.SetRenderWindow(renderWindow)

    light1 = vtkLight()
    light1.SetFocalPoint(0, 0, 0)
    light1.SetPosition(0, 1, 0.2)
    light1.SetColor(colors.GetColor3d('HighNoonSun'))
    light1.SetIntensity(0.3)
    renderer.AddLight(light1)

    light2 = vtkLight()
    light2.SetFocalPoint(0, 0, 0)
    light2.SetPosition(1.0, 1.0, 1.0)
    light2.SetColor(colors.GetColor3d('100W Tungsten'))
    light2.SetIntensity(0.8)
    renderer.AddLight(light2)

    mapper = vtkPolyDataMapper()
    mapper.SetInputData(polyData)

    actor = vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetAmbientColor(colors.GetColor3d('SaddleBrown'))
    actor.GetProperty().SetDiffuseColor(colors.GetColor3d('Sienna'))
    actor.GetProperty().SetSpecularColor(colors.GetColor3d('White'))
    actor.GetProperty().SetSpecular(0.51)
    actor.GetProperty().SetDiffuse(0.7)
    actor.GetProperty().SetAmbient(0.7)
    actor.GetProperty().SetSpecularPower(30.0)
    actor.GetProperty().SetOpacity(1.0)
    renderer.AddActor(actor)

    # Add a plane
    bounds = polyData.GetBounds()

    rnge = [0] * 3
    rnge[0] = bounds[1] - bounds[0]
    rnge[1] = bounds[3] - bounds[2]
    rnge[2] = bounds[5] - bounds[4]
    print('range: ', ', '.join(['{0:0.6f}'.format(i) for i in rnge]))
    expand = 1.0
    thickness = rnge[2] * 0.1
    plane = vtkCubeSource()
    plane.SetCenter((bounds[1] + bounds[0]) / 2.0,
                    bounds[2] - thickness / 2.0,
                    (bounds[5] + bounds[4]) / 2.0)
    plane.SetXLength(bounds[1] - bounds[0] + (rnge[0] * expand))
    plane.SetYLength(thickness)
    plane.SetZLength(bounds[5] - bounds[4] + (rnge[2] * expand))

    planeMapper = vtkPolyDataMapper()
    planeMapper.SetInputConnection(plane.GetOutputPort())

    planeActor = vtkActor()
    planeActor.SetMapper(planeMapper)
    renderer.AddActor(planeActor)

    renderWindow.SetMultiSamples(0)

    shadows = vtkShadowMapPass()

    seq = vtkSequencePass()

    passes = vtkRenderPassCollection()
    passes.AddItem(shadows.GetShadowMapBakerPass())
    passes.AddItem(shadows)
    seq.SetPasses(passes)

    cameraP = vtkCameraPass()
    cameraP.SetDelegatePass(seq)

    # Tell the renderer to use our render pass pipeline
    glrenderer = renderer
    glrenderer.SetPass(cameraP)

    renderer.GetActiveCamera().SetPosition(-0.2, 0.2, 1)
    renderer.GetActiveCamera().SetFocalPoint(0, 0, 0)
    renderer.GetActiveCamera().SetViewUp(0, 1, 0)
    renderer.ResetCamera()
    renderer.GetActiveCamera().Dolly(2.25)
    renderer.ResetCameraClippingRange()
    renderWindow.SetWindowName('Shadows')
    renderWindow.Render()
    renderWindow.SetWindowName('Shadows')

    interactor.Start()


if __name__ == '__main__':
    main()