ShadowLightsDemo - extents of shadows, light frustum, darkened areas

Hi all, this is my first post in this forum.

Long post ahead, because I’ve been trying to learn how lights and shadows work in VTK and i’ve encountered some situations that i cannot explain.

I’ve expressed my concerns on that page (https://github.com/lorensen/VTKExamples/issues/655) where i have received some answers. However I was advised to ask here about further doubts I have.

I’ve looked at some examples from https://github.com/lorensen/VTKExamples. I’ve run my own versions, but I would like to first look at the vanilla version of the demo (the python version in my case):

Here we have a scene with some spotlights, illuminating (partly) a horizontal plane opposite these lights.

image
What I cannot explain is how the illuminated area(s) on the horizontal planes is not an ellipse (at least as far as the plane goes). One can make the planes as big as needed, the illuminated areas will show some straight borders (excluding of course the shadows cast by the other objects in the scene).

To make it simple I’ve reduced the scene to 1 spotlight, 1 plane. The light also has a pyramid prop showing the light frustum. This is what i’m seeing:

It looks like the illuminated area on the horizontal plane is intersection between an ellipse and a quadrilateral. While the first is expected, the straight border (supposedly coming from the intersection of the light’s pyramidal frustum with the horizontal plane) is less obvious.

  • Where does the quadrilateral come from?
  • Why does the light cone not reach the furthest parts of the plane?
  • If it’s because the light frustum is smaller than the cone, why is that so? the light frustum volume should be a super-set of the light cone volume in the first place, right?
  • If the it is the prop the one not show the true frustum of the light, why is that so? is it a bug in the prop?

Code below:

import vtk


def main():
    interactor = vtk.vtkRenderWindowInteractor()

    renderWindow = vtk.vtkRenderWindow()
    renderWindow.SetSize(400, 400)
    renderWindow.SetMultiSamples(0)

    renderWindow.SetAlphaBitPlanes(1)
    interactor.SetRenderWindow(renderWindow)

    renderer = vtk.vtkOpenGLRenderer()
    renderWindow.AddRenderer(renderer)
    renderWindow.SetSize(640, 480)

    x = 5.0
    rectangleSource = vtk.vtkPlaneSource()
    rectangleSource.SetOrigin(-x, 0.0, x)
    rectangleSource.SetPoint1(x, 0.0, x)
    rectangleSource.SetPoint2(-x, 0.0, -x)
    rectangleSource.SetResolution(100, 100)

    rectangleMapper = vtk.vtkPolyDataMapper()
    rectangleMapper.SetInputConnection(rectangleSource.GetOutputPort())

    rectangleMapper.SetScalarVisibility(0)

    shadows = vtk.vtkShadowMapPass()

    seq = vtk.vtkSequencePass()

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

    cameraP = vtk.vtkCameraPass()
    cameraP.SetDelegatePass(seq)

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

    colors = vtk.vtkNamedColors()
    rectangleColor = colors.GetColor3d("Beige")

    rectangleActor = vtk.vtkActor()
    rectangleActor.SetMapper(rectangleMapper)
    rectangleActor.VisibilityOn()
    rectangleActor.GetProperty().SetColor(rectangleColor)

    renderer.AddViewProp(rectangleActor)
    # Spotlights.

    # lighting the box.
    l1 = vtk.vtkLight()
    l1.SetPosition(-4.0, 4.0, -1.0)
    l1.SetFocalPoint(-2.0, 2.0, 0.0)
    l1.SetColor(1.0, 1.0, 1.0)
    l1.PositionalOn()
    renderer.AddLight(l1)
    l1.SwitchOn()

    # For each spotlight, add a light frustum wireframe representation and a cone
    # wireframe representation, colored with the light color.
    angle = l1.GetConeAngle()
    if l1.LightTypeIsSceneLight() and l1.GetPositional() and angle < 180.0:  # spotlight
        la = vtk.vtkLightActor()
        la.SetLight(l1)
        renderer.AddViewProp(la)

    renderer.SetBackground2(colors.GetColor3d("Silver"))
    renderer.SetBackground(colors.GetColor3d("LightGrey"))
    renderer.SetGradientBackground(True)

    renderWindow.Render()
    renderWindow.SetWindowName('ShadowsLightsDemo')

    renderer.ResetCamera()

    camera = renderer.GetActiveCamera()
    camera.Azimuth(40.0)
    camera.Elevation(10.0)

    renderWindow.Render()

    interactor.Start()


if __name__ == '__main__':
    main()

Thank you very much for those who have read thus far.

I’m on windows 10, python 3.7, VTK version 9.0.0