Scene3d.Types.Light coordinates castsShadows
A Light
represents a single source of light in the scene, such as the sun
or a light bulb. Lights are not rendered themselves; they can only be seen by
how they interact with objects in the scene.
The CastsShadows
type is used to indicate either whether a given light
casts shadows. Lights can usually be constructed using Light.castsShadows True
or Light.castsShadows False
, but if you want to use more than four lights in a
scene then the extra lights must be constructed with the special
Light.neverCastsShadows
value. This system allows the first four lights to
have shadows dynamically enabled/disabled at runtime, while using the type
system to guarantee that no more than four lights ever cast shadows.
castsShadows : Basics.Bool -> CastsShadows Basics.Bool
Construct a CastsShadows Bool
value used to indicate whether a given
light casts shadows.
neverCastsShadows : CastsShadows Basics.Never
Construct a special CastsShadows Never
value used to indicate that a given
light never casts shadows.
directional : CastsShadows castsShadows -> { chromaticity : Chromaticity, intensity : Illuminance, direction : Direction3d coordinates } -> Light coordinates castsShadows
Create a directional light given its chromaticity, intensity, direction, and whether or not it casts shadows:
sunlightAtNoon =
Light.directional (Light.castsShadows True)
{ chromaticity = Light.sunlight
, intensity = Illuminance.lux 80000
, direction = Direction3d.negativeZ
}
Note that the direction
is the direction the light is traveling (the direction
of the light, not the direction to the light source from the scene).
Directional lights cast uniform light across the entire scene and result in relatively simple shadows:
(Note that this scene also includes some soft lighting in addition to the directional light.)
point : CastsShadows castsShadows -> { chromaticity : Chromaticity, intensity : LuminousFlux, position : Point3d Length.Meters coordinates } -> Light coordinates castsShadows
Create a point light given its chromaticity, intensity, position, and whether or not it casts shadows:
tableLamp =
Light.point (Light.castsShadows True)
{ chromaticity = Light.incandescent
, intensity = LuminousFlux.lumens 500
, position = Point3d.centimeters 40 50 30
}
Compared to a directional light, the illumination from a point light varies more over the scene (brighter close to the light, less bright further away) and results in more interesting shadows:
(Note that this scene also includes some soft lighting in addition to the point light.)
soft : { upDirection : Direction3d coordinates, chromaticity : Chromaticity, intensityAbove : Illuminance, intensityBelow : Illuminance } -> Light coordinates Basics.Never
Add some 'soft' indirect/environmental lighting to a scene: this is a rough approximation for light coming from all different directions, such as light coming from the sky (as opposed to direct sunlight) or indirect lighting reflected from surrounding surfaces. The intensity of the light will vary smoothly from a given intensity 'above' to 'below', based on given 'up' direction and with a given chromaticity.
For example, a decent approximation to indoors office lighting might be:
Light.soft
{ upDirection = Direction3d.positiveZ
, chromaticity = Light.fluorescent
, intensityAbove = Illuminance.lux 400
, intensityBelow = Illuminance.lux 100
}
Note that soft lighting does not cast shadows. Soft lighting is a great way to make sure the entire scene has some reasonable illumination; the point and directional light examples both include a small amount of soft lighting to 'fill in' otherwise unlit areas. For example, here's the point light example without any additional lighting:
Conversely, soft lighting by itself can be a bit boring, so in many cases you'll want to add one or more point and/or directional lights to add interest:
overhead : { upDirection : Direction3d coordinates, chromaticity : Chromaticity, intensity : Illuminance } -> Light coordinates Basics.Never
A slightly simplified version of Light.soft
with the given intensity
above and zero intensity below. This can be useful if you want color
(chromaticity) to also vary from above to below; for example, for and outdoors
scene you might use two 'overhead' lights with different chromaticities and
opposite 'up' directions to represent light from the blue sky plus some more
neutral-colored light reflected from the surrounding environment:
sky =
Light.overhead
{ upDirection = Direction3d.positiveZ
, chromaticity = Light.skylight
, intensity = Illuminance.lux 20000
}
environment =
Light.overhead
{ upDirection = Direction3d.negativeZ
, chromaticity = Light.daylight
, intensity = Illuminance.lux 15000
}
Note that the environment
light has the 'up' direction set to negative Z
since that light mostly comes from below (reflected from the ground) than above.
ambient : { chromaticity : Chromaticity, intensity : Illuminance } -> Light coordinates Basics.Never
A simple version of Light.soft
with constant intensity light in every
direction. Provided for completeness, but you generally won't want to use this
as it tends to result in very flat, unrealistic-looking scenes:
disabled : Light coordinates castsShadows
A 'light' that does not actually do anything. Can be useful if you have some conditional logic that decides whether a particular light is on or off:
lamp =
if model.lampIsOn then
Light.point (Light.castsShadows True)
{ position = model.lampPosition
, chromaticity = Light.incandescent
, intensity = LuminousFlux.lumens 400
}
else
Light.disabled
Scene3d.Types.Chromaticity
Chromaticity is a precise way of describing color independent of brightness. You can think of it as roughly hue and saturation without value or lightness.
Chromaticity is used for specifying the color of individual lights as well as the white balance to use for the overall scene.
color : Color -> Chromaticity
Extract the chromaticity of a given color. Note that this is a lossy
conversion since it throws away any lightness/brightness information. For
example, any greyscale color value will have chromaticity equal to
Light.daylight
(since that is the standard 'white' chromaticity for the
sRGB color space).
daylight : Chromaticity
The approximate chromaticity of noon daylight; this is a combination of
direct sunlight and blue sky, so is slightly cooler than pure sunlight.
As a result, this is a good default choice for white balance and indirect
lighting, but for direct lighting you'll likely want to use sunlight
,
skylight
, incandescent
or fluorescent
instead.
This is standardized as Illuminant D65, "Noon Daylight", and is the 'white' color of a properly-calibrated sRGB monitor.
sunlight : Chromaticity
An approximate chromaticity value for direct daytime sunlight. This doesn't seem to have an offically standardized value, but 'sunlight' film is apparently calibrated to a color temperature of 5600 K so that is what is used here. (This falls at low end of 'vertical daylight' and above 'horizon daylight', so should be a decent representative value.)
skylight : Chromaticity
An approximate chromaticity value for clear blue sky. There seems to be even less agreement on a representative value to use here, but a color temperature of 12000 K seems fairly reasonable (see e.g. here).
incandescent : Chromaticity
The chromaticity of typical incandescent/tungsten lighting. This is standardized as Illuminant A, "Incandescent/Tungsten".
fluorescent : Chromaticity
The chromaticity of typical fluorescent lighting. This is standardized as Illuminant F2, "Cool White Fluorescent".
colorTemperature : Temperature -> Chromaticity
Specify chromaticity by providing a color temperature.
For example, Light.daylight
is equivalent to
Light.colorTemperature (Temperature.kelvins 5600)
See here for the color temperatures of many common sources of light.
chromaticity : { x : Basics.Float, y : Basics.Float } -> Chromaticity
Specify chromaticity by its xy coordinates in the CIE xyY color space.