Extensible 3D (X3D)
Part 1: Architecture and base components

17 Lighting component

--- X3D separator bar ---

cube 17.1 Introduction

17.1.1 Name

The name of this component is "Lighting". This name shall be used when referring to this component in the COMPONENT statement (see 7.2.5.4 Component statement).

17.1.2 Overview

This clause describes the Lighting component of this part of ISO/IEC 19775. This includes how light sources are defined and positioned as well as how lights effect the rendered image. Table 17.1 provides links to the major topics in this clause.

Table 17.1 — Topics

cube 17.2 Concepts

17.2.1 Light source semantics

17.2.1.1 Overview

The following node types are light source nodes:

PointLight and SpotLight illuminate all objects in the world that fall within their volume of lighting influence regardless of location within the transformation hierarchy (by default, when their global field is TRUE). PointLight defines this volume of influence as a sphere centred at the light (defined by a radius). SpotLight defines the volume of influence as a solid angle defined by a radius and a cut-off angle. DirectionalLight nodes illuminate only the objects descended from the light's parent grouping node, including any descendent children of the parent grouping nodes (by default, when their global field is FALSE).

Shape nodes are illuminated by the sum of all of the lights in the world that affect them. This includes the contribution of both the direct and ambient illumination from light sources. Ambient illumination results from the scattering and reflection of light originally emitted directly by light sources. The amount of ambient light is associated with the individual lights in the scene. This is a gross approximation to how ambient reflection actually occurs in nature.

Any node used as a source of illumination is derived from X3DLightNode. All light sources contain an intensity, a color, and an ambientIntensity field. The intensity field specifies the brightness of the direct emission from the light, and the ambientIntensity specifies the intensity of the ambient emission from the light. Light intensity may range from 0.0 (no light emission) to infinity. The color field specifies the spectral colour properties of both the direct and ambient light emission as an RGB value. The on field specifies whether the light is enabled or disabled. If the value is FALSE, the light is disabled and will not affect any nodes in the scene. If the value is TRUE, the light will affect other nodes according to the 17.2.1.2 Scoping of lights.

Typically lighting intensity values are within range [0,1] for consistent composability of multiple scenes with independent lights.

In the physical lighting model (see 17.2.2.6 Physical lighting model) the intensity value should correspond to:

In the physical lighting model, the ambientIntensity value is unused.

In the case of the unlit lighting model all lights are ignored. See the 17.2.2.4 Unlit lighting model.

17.2.1.2 Scoping of lights

Each light type defines a global field that determines whether the light is global or scoped. Global lights illuminate all objects that fall within their volume of lighting influence. Scoped lights only illuminate objects that are in the same transformation hierarchy as the light; i.e., only the children and descendants of its enclosing parent group are illuminated. This allows the creation of realistic effects such as lights that illuminate a single room.

17.2.2 Lighting model

17.2.2.1 Introduction

The X3D lighting model provides detailed equations that specify the colours to apply to each geometric object. For each object, the values of the material, color, and/or texture currently being applied to the object are combined with the lights illuminating the object and the currently bound X3DFogObject (if specified). These equations are designed to simulate the physical properties of light striking a surface.

If a programmable shader is defined for an Appearance node, the lighting model shall be disabled and replaced by the functionality implemented by the shader program. See 31 Programmable shaders component for more information.

NOTE  Geometry nodes that represent lines or points do not support lighting.

17.2.2.2 Texture sampling

A grayscale texture is exactly equivalent to using an RGB texture with all 3 components (red, green, blue) equal.

A texture without an alpha channel is exactly equivalent to using a texture with an alpha channel filled with 1 (indicating opaque).

17.2.2.3 Common definitions for all lighting models

The declarations and definitions below are presented using pseudocode similar to typical shading language code (see 31.2.2.1 Shader language options).

The mixTexture(vector4color,X3DTextureNodetexture) function, used in the equations below, takes care of mixing an RGBA color with the RGBA value sampled from the texture at the given shape point.

The lerp(floatfactor,vectorAnyx,vectorAnyy) function performs a standard linear interpolation, applicable to scalars or vectors of any dimension:

lerp(factor, x, y) = x * (1 - factor) + y * factor = x + (y - x) * factor

The occlusion(vector4color) function, used in the equations below for Phong and physical lighting model, is used to apply the occlusionTexture effect that can be specified in these nodes.

The applyColorPerVertex(vector4color) is used to change the color in case geometry uses Color or ColorRGBA nodes. All the lighting models use this function, although it affects a different parameter: emissiveParameter in case of unlit model, diffuseParameter in case of Phong model, and baseParameter in case of physical model. The function returns:

The future X3D versions may introduce an option for Color and ColorRGBA to multiply the input color, instead of replacing it.

Moreover we define the following vectors:

The following definitions are specific to a light source i, which is indicated by a subscript in this text:

Table 17.4 — Calculation of the spotlight factor

Condition (in order) spot i =
lighti is PointLight or DirectionalLight 1
spotAngle ≥ SpotLight.cutOffAngle 0
spotAngle ≤ SpotLight.beamWidth 1
SpotLight.beamWidth  < spotAngle < lightSource.cutOffAngle (spotAngle - SpotLight.cutOffAngle) / (SpotLight.beamWidth - SpotLight.cutOffAngle)

The applyFog(vector4color) is used to change the color using the fog. Is it used by all lighting models, as the last operation performed on the color. The definition is:

applyFog(color) = lerp(fogInterpolant(fogDistance), fogColor, color)

where:

Table 17.5 — Calculation of the fogInterpolant(FogDistance) function:

Condition fogInterpolant(fogDistance) =
no fog 1
fogType "LINEAR", fogDistance < fogVisibility (fogVisibility - fogDistance) / fogVisibility
fogType "LINEAR", fogDistance > fogVisibility 0
fogType "EXPONENTIAL", fogDistance < fogVisibility exp(- FogDistance / (fogVisibility - fogDistance ) )
fogType "EXPONENTIAL", fogDistance > fogVisibility 0

17.2.2.4 Unlit lighting model

A Shape node is unlit if either of the following is true:

  1. The shape's appearance field is NULL (default).
  2. The material field in the Appearance node is NULL (default).
  3. The material field in the Appearance node contains a node of type UnlitMaterial.

In the first two cases above, the rendering is exactly equivalent as if the Appearance node was provided (not NULL), and the material field inside contained an UnlitMaterial with all the fields at their default. Effectively, it means a white untextured unlit material is the default.

NOTE  Geometry nodes that represent lines or points do not support lighting if the normal vectors for them are not provided.

If the shape is unlit, the RGBA color of the shape at each point on the shape's geometry is calculated using this equation:

fragmentColor = applyFog(mixTexture(applyColorPerVertex(emissiveParameter), emissiveTextureParameter))

where:

17.2.2.5 Phong lighting model

The Shape node is lit with a Phong lighting model if the Appearance node is specified for the Shape, and the material field contains a Material node.

NOTE   This node is simply called Material for historical reasons. Conceptually, you should think about it now as a PhongMaterial.

The rendered fragment (pixel) color is determined by these equations:

fragmentColor = applyFog(emissiveParameter + occlusion(sumOverAllLights(lightContributioni)))

lightContributioni= oni × shadowTesti × lightColori × attenuationi × spoti × (ambienti+ diffusei+ speculari)

An ideal X3D implementation will evaluate the following lighting equation at each point on a lit surface. The means that we advise using Phong shading and assume it when writing equations below. For implementations that perform Gouraud shading see 17.2.2.8 Gouraud shading section.

The meaning of all the terms is explained below.

Material parameters

First, the parameters whose value does not depend on the light source:

The material diffuseParameter is calculated as follows:

diffuseParameter = mixTexture(applyColorPerVertex(diffuseParameter), diffuseTextureParameter) where:

The remaining parameters are defined below:

In the above equations, if the given texture is NULL then behave as if the textureSample(texture) returned a white opaque value (1, 1, 1, 1).

Light parameters

Now we can define terms that depend on the light source:

The Phong lighting equations are based on the simple illumination equations given in [FOLEY] and [OPENGL].

17.2.2.6 Physical lighting model

The Shape node is lit with a Physical lighting model if the Appearance node are specified for the Shape, and the material field contains a PhysicalMaterial node. We perform in this case a physically-based rendering.

The rendered fragment (pixel) color is determined by these equations:

fragmentColor = applyFog(emissiveParameter + occlusion(sumOverAllLights(lightContributioni)))

lightContributioni= oni × shadowTesti × lightColori × attenuationi × spoti × physicalLightContributioni

The input values used by the physical lighting equation are as follows:

baseParameter = mixTexture(applyColorPerVertex(baseParameter), baseTextureParameter) where:

metallicParameter = PhysicalMaterial.metallic × textureSample(PhysicalMaterial.metallicRoughnessTexture).b

roughnessParameter = PhysicalMaterial.roughness × textureSample(PhysicalMaterial.metallicRoughnessTexture).g

If the metallicRoughnessTexture is NULL, then metallicParameter and roughnessParameter are just equal to (respectively) metallic and roughness values given by the PhysicalMaterial node.

The physical lighting model uses the baseParameter, metallicParameter and roughnessParameter to calculate the physicalLightContributioni value in accordance with the physically based rendering equations as specified in 2.[GLTF].

17.2.2.7 Gouraud shading model

An ideal X3D implementation will evaluate the lighting equation at each point on a lit surface. The lighting equations in previous sections assume that you use Phong shading (not to be confused with Phong lighting model). In case of Phong shading, lighting is calculated at each fragment (pixel of the screen).

However, some implementations perform Gouraud shading, either by default, or as an option for the user (for efficiency), or as a fallback for an older GPUs. In such case, the lighting equations given above cannot be reproduced precisely. In Gouraud shading, you calculate lighting per-vertex, which means that it does not make sense to use texture information to modify material parameters.

In case when Gouraud shading is used we recommend this algorithm:

This recommendation tries to preserve the intended look as much as possible in Gouraud shading.

NOTE   This recommendation actually does not change anything in case of UnlitMaterial. And this is correct, Gouraud shading actually does not change how the UnlitMaterial can be implemented.

NOTE   When using PhysicalMaterial on older hardware, some implementations may fall back to the Phong lighting model. If this is necessary, we recommend using PhysicalMaterial.baseColor as the Phong diffuse factor, and PhysicalMaterial.baseTexture as the texture to multiply the resulting color.

17.2.2.8 Shadows

Geometric objects can cast shadows, meaning that the amount of light reaching a given surface is decreased if a light source is obscured by occluding geometry. Intervening geometry is only considered for occlusion effects when the X3DShapeNode field castShadow is TRUE.

Multiple light sources can have shadows enabled. Lighting contributions from each light source, and the intensity of corresponding shadows that reduce light available at end points, are each computed independently before reaching lit surface points.

High-fidelity physical effects such as umbra, penumbra and antumbra may be optionally applied. X3D browser implementations are allowed some variations in shadow rendering.

cube 17.3 Abstract types

17.3.1 X3DLightNode

X3DLightNode : X3DChildNode { 
  SFFloat [in,out] ambientIntensity 0     [0,1]
  SFColor [in,out] color            1 1 1 [0,1]
  SFBool  [in,out] global           FALSE
  SFFloat [in,out] intensity        1     [0,∞) 
  SFNode  [in,out] metadata         NULL  [X3DMetadataObject]
  SFBool  [in,out] on               TRUE
  SFBool  [in,out] shadows          FALSE
  SFFloat [in,out] shadowIntensity  1     [0,1]
}

The X3DLightNode abstract node type is the base type from which all node types that serve as light sources are derived. A description of the ambientIntensity, color, intensity, and on fields is in 17.2.1 Light source semantics. A description of the global field is in 17.2.1.2 Scoping of lights.

The shadows field indicates whether or not lighting from this node casts a shadow behind illuminated X3DShapeNode geometry.

The shadowIntensity field defines how much light is obscured by shapes that cast shadows, ranging from 0 (light not obscured, no visible shadows) to 1 (light completely obscured, full-intensity shadows). The shadowIntensity field has no effect when the shadows field is FALSE.

cube 17.4 Node reference

17.4.1 DirectionalLight

DirectionalLight : X3DLightNode {
  SFFloat [in,out] ambientIntensity 0      [0,1]
  SFColor [in,out] color            1 1 1  [0,1]
  SFVec3f [in,out] direction        0 0 -1 (-∞,∞)
  SFBool  [in,out] global           FALSE
  SFFloat [in,out] intensity        1      [0,∞)
  SFNode  [in,out] metadata         NULL   [X3DMetadataObject]
  SFBool  [in,out] on               TRUE
  SFBool  [in,out] shadows          FALSE
  SFFloat [in,out] shadowIntensity  1     [0,1]
}

The DirectionalLight node defines a directional light source that illuminates along rays parallel to a given 3-dimensional vector. A description of the ambientIntensity, color, intensity, and on fields is in 17.2.1 Light source semantics. A description of the global field is in 17.2.1.2 Scoping of lights.

The direction field specifies the direction vector of the illumination emanating from the light source in the local coordinate system. Light is emitted along parallel rays from an infinite distance away. A directional light source illuminates only the objects in its enclosing parent group. The light may illuminate everything within this coordinate system, including all children and descendants of its parent group. The accumulated transformations of the parent nodes affect the light.

DirectionalLight nodes do not attenuate with distance. A precise description of X3D's lighting equations is contained in 17.2.2 Lighting model.

17.4.2 EnvironmentLight

Editors NOTE  This preliminary node definition indicates intent to implement Image Based Lighting (IBL) as defined by Khronos glTF specification. Current activity by X3D practitioners is focused on converged design, implementation and evaluation using the open-source Castle Game Engine and X3DOM X3D browsers. Further improvements are expected.

EnvironmentLight : X3DLightNode {
  SFFloat    [in,out] ambientIntensity     0        [0,1]
  SFColor    [in,out] color                1 1 1    [0,1]
  SFNode     [in,out] diffuse              NULL     [X3DSingleTextureNode] # .DDS format
  SFNode     [in,out] diffuseTexture       NULL     [X3DEnvironmentTextureNode]
  MFFloat    [in,out] diffuseCoefficients  []
  SFBool     [in,out] global               FALSE
  SFFloat    [in,out] intensity            1        [0,∞)
  SFNode     [in,out] metadata             NULL     [X3DMetadataObject]
  SFBool     [in,out] on                   TRUE
  SFRotation [in,out] rotation             0 0 1 0  [-1,1] or (-∞,∞)
  SFBool     [in,out] shadows              FALSE
  SFFloat    [in,out] shadowIntensity      1        [0,1]
  SFNode     [in,out] specularTexture      NULL     [X3DEnvironmentTextureNode]
}

The EnvironmentLight node supports Image Based Lighting (IBL) by specifying light-source intensity around a given location (i.e., the environment) as a cube map. EnvironmentLight defines both specular radiance and diffuse irradiance.

The diffuseTexture and specularTexture fields define diffuse and specular lighting modifications, respectively.

The diffuseCoefficients field provides a 3 x 9 array of float values that declares spherical harmonic coefficients for irradiance up to l=2, corresponding to glTF irradianceCoefficients field. The diffuseCoefficients field overrides the diffuseTexture field if both are provided.

A description of the global field is in 17.2.1.2 Scoping of lights.

17.4.2 PointLight

PointLight : X3DLightNode {
  SFFloat [in,out] ambientIntensity 0     [0,1]
  SFVec3f [in,out] attenuation      1 0 0 [0,∞)
  SFColor [in,out] color            1 1 1 [0,1]
  SFBool  [in,out] global           TRUE
  SFFloat [in,out] intensity        1     [0,∞)
  SFVec3f [in,out] location         0 0 0 (-∞,∞)
  SFNode  [in,out] metadata         NULL  [X3DMetadataObject]
  SFBool  [in,out] on               TRUE
  SFFloat [in,out] radius           100   [0,∞)
  SFBool  [in,out] shadows          FALSE
  SFFloat [in,out] shadowIntensity  1     [0,1]
}

The PointLight node specifies a point light source at a 3D location in the local coordinate system. A point light source emits light equally in all directions; that is, it is omnidirectional. PointLight nodes are specified in the local coordinate system and are affected by ancestor transformations. A description of the global field is in 17.2.1.2 Scoping of lights.

Subclause 17.2.1 Light source semantics, contains a detailed description of the ambientIntensity, color, and intensity fields.

A PointLight node illuminates geometry within radius length base units of its location. Both radius and location are affected by ancestors' transformations (scales affect radius and transformations affect location). The radius field shall be greater than or equal to zero.

PointLight node's illumination falls off with distance as specified by three attenuation coefficients. The attenuation factor is:

1/max(attenuation[0] + attenuation[1] × r + attenuation[2] × r 2,  1)

where r is the distance from the light to the surface being illuminated. The default is no attenuation. An attenuation value of (0, 0, 0) is identical to (1, 0, 0). Attenuation values shall be greater than or equal to zero. A detailed description of X3D's lighting equations is contained in 17.2.2 Lighting model.

17.4.3 SpotLight

SpotLight : X3DLightNode {
  SFFloat [in,out] ambientIntensity 0        [0,1]
  SFVec3f [in,out] attenuation      1 0 0    [0,∞)
  SFFloat [in,out] beamWidth        π*3/16 /4  (0,π/2]
  SFColor [in,out] color            1 1 1    [0,1]
  SFFloat [in,out] cutOffAngle      π/2      (0,π/2]
  SFVec3f [in,out] direction        0 0 -1   (-∞,∞)
  SFBool  [in,out] global           TRUE
  SFFloat [in,out] intensity        1        [0,∞)
  SFVec3f [in,out] location         0 0 0    (-∞,∞)
  SFNode  [in,out] metadata         NULL     [X3DMetadataObject]
  SFBool  [in,out] on               TRUE
  SFFloat [in,out] radius           100      [0,∞)
  SFBool  [in,out] shadows          FALSE
  SFFloat [in,out] shadowIntensity  1        [0,1]
}

The SpotLight node defines a light source that emits light from a specific point along a specific direction vector and constrained within a solid angle. Spotlights may illuminate geometry nodes that respond to light sources and intersect the solid angle defined by the SpotLight. Spotlight nodes are specified in the local coordinate system and are affected by ancestors' transformations. A description of the global field is in 17.2.1.2 Scoping of lights.

A detailed description of ambientIntensity, color, intensity, and the lighting equations of X3D is provided in 17.2.1 Light source semantics. More information on lighting concepts can be found in 17.2.2 Lighting model, including a detailed description of the X3D lighting equations.

The location field specifies a translation offset of the centre point of the light source from the light's local coordinate system origin. This point is the apex of the solid angle which bounds light emission from the given light source. The direction field specifies the direction vector of the light's central axis defined in the local coordinate system.

The on field specifies whether the light source emits light. If on is TRUE, the light source is emitting light and may illuminate geometry in the scene. If on is FALSE, the light source does not emit light and does not illuminate any geometry.

The radius field specifies the radial extent of the solid angle and the maximum distance from location that may be illuminated by the light source. The light source does not emit light outside this radius. The radius shall be greater than or equal to zero.

Both radius and location are affected by ancestors' transformations (scales affect radius and transformations affect location).

The cutOffAngle field specifies the outer bound of the solid angle. The light source does not emit light outside of this solid angle. The beamWidth field specifies an inner solid angle in which the light source emits light at uniform full intensity. The light source's emission intensity drops off from the inner solid angle (beamWidth) to the outer solid angle (cutOffAngle) as described in the following equations:

    angle = the angle between the Spotlight's direction vector
            and the vector from the Spotlight location to the point
            to be illuminated

    if (angle ≥ cutOffAngle):
        multiplier = 0
    else if (angle ≤ beamWidth):
        multiplier = 1
    else:
        multiplier = (angle - cutOffAngle) / (beamWidth - cutOffAngle)
    intensity(angle) = SpotLight.intensity × multiplier

If the beamWidth is greater than the cutOffAngle, beamWidth is defined to be equal to the cutOffAngle and the light source emits full intensity within the entire solid angle defined by cutOffAngle. Both beamWidth and cutOffAngle shall be greater than 0.0 and less than or equal to π/2. Figure 17.1 depicts the beamWidth, cutOffAngle, direction, location, and radius fields of the SpotLight node.

SpotLight node

Figure 17.1 — SpotLight node

SpotLight illumination falls off with distance as specified by three attenuation coefficients. The attenuation factor is:

1 /max(attenuation[0] + attenuation[1] × r + attenuation[2] × r2 , 1 )

where r is the distance from the light to the surface being illuminated. The default is no attenuation. An attenuation value of (0, 0, 0) is identical to (1, 0, 0). Attenuation values shall be greater than or equal to zero. A detailed description of X3D's lighting equations is contained in 17.2.2 Lighting model.

cube 17.5 Support levels

The Lighting component provides three levels of support as specified in Table 17.6.

Table 17.6 — Lighting component support levels

Level Prerequisites Nodes/Features Support
1 Core 1
Shape 1
X3DLightNode (abstract) n/a
DirectionalLight Not scoped by parent Group or Transform.
Support for Gouraud and Phong shading.
2 Core 1
Shape 1
 
All Level 1 Lighting nodes All fields as supported in Level 1.
PointLight radius optionally supported. Linear attenuation.
SpotLight beamWidth optionally supported. radius optionally supported. Linear attenuation.
3 Core 1
Shape 2
All Level 2 Lighting nodes All fields fully supported.
EnvironmentLight All fields fully supported.
Support for Physical and Unlit lighting models.

--- X3D separator bar ---