The lighting module provides various light types for illuminating 3D scenes.
import io.materia.light.*
Abstract base class for all lights.
| Property | Type | Default | Description | |----------|------|---------|-------------| | color | Color | WHITE | Light color | | intensity | Float | 1.0 | Light intensity |
// Copy light properties
fun copy(source: Light): Light
// Clone light
fun clone(): Light
// Dispose resources
fun dispose()
Uniform light that illuminates all objects equally from all directions.
class AmbientLight(
color: Color = Color.WHITE,
intensity: Float = 1f
)
| Property | Type | Description | |----------|------|-------------| | color | Color | Light color | | intensity | Float | Light intensity |
// Add ambient light for base illumination
val ambient = AmbientLight(Color(0x404040), 0.4f)
scene.add(ambient)
Light that emits parallel rays in a specific direction (like sunlight).
class DirectionalLight(
color: Color = Color.WHITE,
intensity: Float = 1f
)
| Property | Type | Default | Description | |----------|------|---------|-------------| | color | Color | WHITE | Light color | | intensity | Float | 1.0 | Light intensity | | target | Object3D | auto | Look-at target | | shadow | DirectionalLightShadow | auto | Shadow settings | | castShadow | Boolean | false | Enable shadows |
class DirectionalLightShadow {
var mapSize: Vector2 = Vector2(512, 512) // Shadow map resolution
var camera: OrthographicCamera // Shadow camera
var bias: Float = 0f // Shadow bias
var normalBias: Float = 0f // Normal-based bias
var radius: Float = 1f // PCF radius
var blurSamples: Int = 8 // Blur samples
}
// Main sun light
val sun = DirectionalLight(Color(0xffffff), 1.0f)
sun.position.set(5f, 10f, 7.5f)
scene.add(sun)
// With shadows
sun.castShadow = true
sun.shadow.mapSize.set(2048f, 2048f)
sun.shadow.camera.near = 0.5f
sun.shadow.camera.far = 50f
sun.shadow.camera.left = -10f
sun.shadow.camera.right = 10f
sun.shadow.camera.top = 10f
sun.shadow.camera.bottom = -10f
sun.shadow.bias = -0.0001f
// Change direction
sun.target.position.set(0f, 0f, 0f)
scene.add(sun.target)
Omnidirectional light emitting from a single point.
class PointLight(
color: Color = Color.WHITE,
intensity: Float = 1f,
distance: Float = 0f,
decay: Float = 2f
)
| Property | Type | Default | Description | |----------|------|---------|-------------| | color | Color | WHITE | Light color | | intensity | Float | 1.0 | Light intensity | | distance | Float | 0 | Maximum range (0 = infinite) | | decay | Float | 2 | Decay rate (physically correct = 2) | | shadow | PointLightShadow | auto | Shadow settings | | castShadow | Boolean | false | Enable shadows |
class PointLightShadow {
var mapSize: Vector2 = Vector2(512, 512)
var camera: PerspectiveCamera // Shadow camera (90° FOV)
var bias: Float = 0f
var normalBias: Float = 0f
var radius: Float = 1f
}
// Lamp light
val lamp = PointLight(Color(0xffaa00), 1.5f, 10f, 2f)
lamp.position.set(0f, 3f, 0f)
scene.add(lamp)
// With shadows (expensive - renders 6 shadow maps)
lamp.castShadow = true
lamp.shadow.mapSize.set(1024f, 1024f)
lamp.shadow.camera.near = 0.1f
lamp.shadow.camera.far = 15f
// Animate
fun animate(time: Float) {
lamp.position.x = sin(time) * 3f
lamp.position.z = cos(time) * 3f
}
Cone-shaped light emitting from a point in a direction.
class SpotLight(
color: Color = Color.WHITE,
intensity: Float = 1f,
distance: Float = 0f,
angle: Float = PI / 3,
penumbra: Float = 0f,
decay: Float = 2f
)
| Property | Type | Default | Description | |----------|------|---------|-------------| | color | Color | WHITE | Light color | | intensity | Float | 1.0 | Light intensity | | distance | Float | 0 | Maximum range | | angle | Float | PI/3 | Cone angle (radians, max PI/2) | | penumbra | Float | 0 | Soft edge (0-1) | | decay | Float | 2 | Decay rate | | target | Object3D | auto | Look-at target | | shadow | SpotLightShadow | auto | Shadow settings | | castShadow | Boolean | false | Enable shadows | | map | Texture? | null | Projector texture |
class SpotLightShadow {
var mapSize: Vector2 = Vector2(512, 512)
var camera: PerspectiveCamera
var bias: Float = 0f
var normalBias: Float = 0f
var radius: Float = 1f
var focus: Float = 1f // Shadow camera focus
}
// Flashlight
val flashlight = SpotLight(
color = Color.WHITE,
intensity = 2f,
distance = 20f,
angle = PI / 8,
penumbra = 0.3f
)
flashlight.position.set(0f, 5f, 5f)
scene.add(flashlight)
// Point at target
flashlight.target.position.set(0f, 0f, 0f)
scene.add(flashlight.target)
// With shadows
flashlight.castShadow = true
flashlight.shadow.mapSize.set(1024f, 1024f)
flashlight.shadow.camera.near = 0.5f
flashlight.shadow.camera.far = 25f
flashlight.shadow.focus = 1f
// Projector texture (gobo)
flashlight.map = textureLoader.load("textures/gobo.png")
Rectangular area light (soft box lighting).
class RectAreaLight(
color: Color = Color.WHITE,
intensity: Float = 1f,
width: Float = 10f,
height: Float = 10f
)
| Property | Type | Default | Description | |----------|------|---------|-------------| | color | Color | WHITE | Light color | | intensity | Float | 1.0 | Light intensity | | width | Float | 10 | Light width | | height | Float | 10 | Light height |
MeshStandardMaterial and MeshPhysicalMaterial// Soft studio light
val areaLight = RectAreaLight(Color(0xffffff), 5f, 4f, 2f)
areaLight.position.set(-5f, 5f, 5f)
areaLight.lookAt(Vector3.ZERO)
scene.add(areaLight)
// Helper for visualization
val helper = RectAreaLightHelper(areaLight)
scene.add(helper)
Gradient light from sky color to ground color.
class HemisphereLight(
skyColor: Color = Color.WHITE,
groundColor: Color = Color.WHITE,
intensity: Float = 1f
)
| Property | Type | Default | Description | |----------|------|---------|-------------| | color | Color | WHITE | Sky color | | groundColor | Color | WHITE | Ground color | | intensity | Float | 1.0 | Light intensity |
// Outdoor ambient
val hemi = HemisphereLight(
skyColor = Color(0x87ceeb), // Sky blue
groundColor = Color(0x362d1a), // Brown earth
intensity = 0.6f
)
scene.add(hemi)
Light probe for image-based lighting.
class LightProbe(
sh: SphericalHarmonics3 = SphericalHarmonics3(),
intensity: Float = 1f
)
| Property | Type | Description | |----------|------|-------------| | sh | SphericalHarmonics3 | Spherical harmonics coefficients | | intensity | Float | Probe intensity |
// Create probe from environment map
val probe = LightProbeGenerator.fromCubeTexture(cubeTexture)
probe.intensity = 0.5f
scene.add(probe)
// Enable shadows on renderer
renderer.shadowMap.enabled = true
renderer.shadowMap.type = ShadowMapType.PCFSoft
// Shadow map types
enum class ShadowMapType {
BASIC, // No filtering
PCF, // Percentage-closer filtering
PCF_SOFT, // Soft PCF
VSM // Variance shadow mapping
}
// Cast shadows
mesh.castShadow = true
// Receive shadows
mesh.receiveShadow = true
// Materials auto-receive if receiveShadow is true
// Use smaller shadow maps for less important lights
fill.castShadow = true
fill.shadow.mapSize.set(256f, 256f)
// Tight shadow camera bounds
directional.shadow.camera.left = -5f
directional.shadow.camera.right = 5f
directional.shadow.camera.top = 5f
directional.shadow.camera.bottom = -5f
// Update shadow camera
directional.shadow.camera.updateProjectionMatrix()
// Bias to prevent shadow acne
directional.shadow.bias = -0.0001f
directional.shadow.normalBias = 0.02f
val helper = DirectionalLightHelper(directionalLight, 5f, Color.YELLOW)
scene.add(helper)
val helper = PointLightHelper(pointLight, 1f, Color.RED)
scene.add(helper)
val helper = SpotLightHelper(spotLight, Color.GREEN)
scene.add(helper)
val helper = HemisphereLightHelper(hemisphereLight, 5f)
scene.add(helper)
val helper = RectAreaLightHelper(rectAreaLight)
scene.add(helper)
// Key light (main illumination)
val key = DirectionalLight(Color(0xffffff), 1.0f)
key.position.set(5f, 5f, 5f)
key.castShadow = true
scene.add(key)
// Fill light (soften shadows)
val fill = DirectionalLight(Color(0x8888ff), 0.3f)
fill.position.set(-5f, 3f, 0f)
scene.add(fill)
// Back light (rim/separation)
val back = DirectionalLight(Color(0xffff88), 0.5f)
back.position.set(0f, 5f, -5f)
scene.add(back)
// Ambient fill
val ambient = AmbientLight(Color(0x404040), 0.2f)
scene.add(ambient)
// Sun
val sun = DirectionalLight(Color(0xffffd4), 1.2f)
sun.position.set(50f, 100f, 50f)
sun.castShadow = true
scene.add(sun)
// Sky/ground hemisphere
val hemi = HemisphereLight(
skyColor = Color(0x87ceeb),
groundColor = Color(0xb97a20),
intensity = 0.5f
)
scene.add(hemi)
// Soft area lights
val softbox1 = RectAreaLight(Color.WHITE, 5f, 2f, 2f)
softbox1.position.set(-3f, 3f, 3f)
softbox1.lookAt(Vector3.ZERO)
scene.add(softbox1)
val softbox2 = RectAreaLight(Color.WHITE, 3f, 2f, 2f)
softbox2.position.set(3f, 2f, 3f)
softbox2.lookAt(Vector3.ZERO)
scene.add(softbox2)
// Background light
val back = RectAreaLight(Color(0x8888ff), 2f, 4f, 4f)
back.position.set(0f, 2f, -3f)
back.lookAt(Vector3.ZERO)
scene.add(back)
// Single point light (lamp/candle)
val point = PointLight(Color(0xff6600), 1f, 10f, 2f)
point.position.set(0f, 2f, 0f)
point.castShadow = true
scene.add(point)
// Very dim ambient
val ambient = AmbientLight(Color(0x101020), 0.1f)
scene.add(ambient)
// Animate flicker
fun animate(time: Float) {
point.intensity = 1f + sin(time * 10f) * 0.1f + random() * 0.05f
}