X3DLightNode : X3DChildNode {
  SFFloat [in,out] ambientIntensity 0
    range: [0,1]
  SFColor [in,out] color            1 1 1
    range: [0,1]
  SFBool  [in,out] global           FALSE
    change: chEverything
  SFFloat [in,out] intensity        1
    range: [0,1]
  SFBool  [in,out] on               TRUE

  # CASTLE GAME ENGINE EXTENSIONS:
  MFNode     []            effects               []
    range: Effect
    change: chEverything
  SFBool     [in,out]      shadowVolumes         FALSE
    change: chLightForShadowVolumes
}

X3DPunctualLightNode : X3DLightNode {
  # CASTLE GAME ENGINE EXTENSIONS:
  SFBool     []            shadows               FALSE
    change: chShadowMaps
  SFBool     [in,out]      shadowVolumesMain     FALSE
    doc: Does this light determine shadows (when using shadow volumes). Ignored if not @link(ShadowVolumes).
    change: chLightForShadowVolumes
  SFBool     [in,out]      showProxyGeometry     FALSE
    doc: InstantReality extension, see [http://instant-reality.com/documentation/nodetype/Light/].
  SFFloat    [in,out]      projectionNear        0
    range: > 0
    doc: Projection near, for shadow maps. See https://castle-engine.io/x3d_extensions_shadow_maps.php#section_light_parameters . }
    # We want to set UpdateNeeded := true for all GeneratedShadowMap using
    # this light. For now, simply send chVisibleGeometry that will
    # force updating all GeneratedShadowMaps.
    change: chVisibleGeometry
  SFFloat    [in,out]      projectionFar         0
    range: anything > projectionNear
    doc: Projection far, for shadow maps. See https://castle-engine.io/x3d_extensions_shadow_maps.php#section_light_parameters . }
    # We want to set UpdateNeeded := true for all GeneratedShadowMap using
    # this light. For now, simply send chVisibleGeometry that will
    # force updating all GeneratedShadowMaps.
    change: chVisibleGeometry
  SFVec3f    [in,out]      up                    0 0 0
    doc: View up vector, for shadow maps. See https://castle-engine.io/x3d_extensions_shadow_maps.php#section_light_parameters . }
    # We want to set UpdateNeeded := true for all GeneratedShadowMap using
    # this light. For now, simply send chVisibleGeometry that will
    # force updating all GeneratedShadowMaps.
    change: chVisibleGeometry
  SFNode     []            defaultShadowMap      NULL
    range: GeneratedShadowMap
    doc: Shadow map used by this light source. See https://castle-engine.io/x3d_extensions_shadow_maps.php#section_light_parameters . }
    change: chEverything
}

# We add abstract X3DDirectionalLight, not present in X3D spec.
# This is an ancestor for X3D DirectionalLight and VRML 1.0 DirectionalLight.
X3DDirectionalLightNode : X3DPunctualLightNode {
  SFVec3f [in,out] direction        0 0 -1
    range: (-Inf,Inf)
    change: chLightLocationDirection

  # NOTE: global by default is FALSE

  # CASTLE GAME ENGINE EXTENSIONS:
  SFVec4f    [in,out]      projectionRectangle   0 0 0 0
    range: left, bottom, right, top; must be left < right and bottom < top
    # We want to set UpdateNeeded := true for all GeneratedShadowMap using
    # this light. For now, simply send chVisibleGeometry that will
    # force updating all GeneratedShadowMaps.
    change: chVisibleGeometry
  SFVec3f    [in,out]      projectionLocation    0 0 0
    # We want to set UpdateNeeded := true for all GeneratedShadowMap using
    # this light. For now, simply send chVisibleGeometry that will
    # force updating all GeneratedShadowMaps.
    change: chVisibleGeometry
}

# We add abstract X3DPositionalLightNode, not present in X3D spec.
# This is an ancestor for at least X3D PointLight, X3D SpotLight,
# VRML 1.0 PointLight, VRML 1.0 SpotLight.
X3DPositionalLightNode : X3DPunctualLightNode {
  # NOTE: global by default is TRUE

  SFVec3f [in,out] attenuation      1 0 0
    range: 0,Inf)
  SFVec3f [in,out] location         0 0 0
    range: 0 0 0 (-Inf,Inf)
    change: chLightLocationDirection
  SFFloat [in,out] radius           100
    # As an extension to X3D, CGE allows radius -1 to indicate "no radius"
    range: [0,Inf) or -1
    change: chLightInstanceProperty
}

X3DPointLightNode : X3DPositionalLightNode {
}

DirectionalLight : X3DDirectionalLightNode {
}

PointLight : X3DPointLightNode {
}

SpotLight : X3DPositionalLightNode {
  SFFloat [in,out] beamWidth        Pi*3/16
    range: (0,Pi/2]
  SFFloat [in,out] cutOffAngle      Pi/4
    range: (0,Pi/2]
  SFVec3f [in,out] direction        0 0 -1
    range: (-Inf,Inf)
    change: chLightLocationDirection

  # CASTLE GAME ENGINE EXTENSIONS:
  SFFloat    [in,out]      projectionAngle       0
    # We want to set UpdateNeeded := true for all GeneratedShadowMap using
    # this light. For now, simply send chVisibleGeometry that will
    # force updating all GeneratedShadowMaps.
    change: chVisibleGeometry
    angle
}

EnvironmentLight : X3DLightNode {
  SFNode  [in,out]  diffuseTexture   NULL
    range: X3DEnvironmentTextureNode
  SFNode  [in,out]  specularTexture  NULL
    range: X3DEnvironmentTextureNode
}
