lighting-environment
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseLighting and Environment in Decentraland
Decentraland 中的光照与环境
Point Lights
Point Light
Emit light in all directions from a position:
typescript
import { engine, Transform, LightSource } from '@dcl/sdk/ecs'
import { Vector3, Color3 } from '@dcl/sdk/math'
const light = engine.addEntity()
Transform.create(light, { position: Vector3.create(8, 3, 8) })
LightSource.create(light, {
type: LightSource.Type.Point({}),
color: Color3.White(),
intensity: 16000 // candela
})从某个位置向所有方向发射光线:
typescript
import { engine, Transform, LightSource } from '@dcl/sdk/ecs'
import { Vector3, Color3 } from '@dcl/sdk/math'
const light = engine.addEntity()
Transform.create(light, { position: Vector3.create(8, 3, 8) })
LightSource.create(light, {
type: LightSource.Type.Point({}),
color: Color3.White(),
intensity: 16000 // candela
})Colored Point Light
彩色 Point Light
typescript
LightSource.create(light, {
type: LightSource.Type.Point({}),
color: Color3.create(1, 0.5, 0), // Warm orange
intensity: 16000,
range: 15 // Maximum distance in meters
})Defaults (from the protocol): true, white, 16000 candela, -1 (auto), false. is (RGB, each 0–1).
activecolorintensityrangeshadowcolorColor3typescript
LightSource.create(light, {
type: LightSource.Type.Point({}),
color: Color3.create(1, 0.5, 0), // Warm orange
intensity: 16000,
range: 15 // Maximum distance in meters
})默认值(来自协议): 为 , 为白色, 为 16000 坎德拉, 为 -1(自动), 为 。 的类型为 (RGB,每个分量的范围为 0–1)。
activetruecolorintensityrangeshadowfalsecolorColor3Spot Lights
Spot Light
Emit a cone of light in a direction:
typescript
import { Quaternion } from '@dcl/sdk/math'
const spotlight = engine.addEntity()
Transform.create(spotlight, {
position: Vector3.create(8, 4, 8),
rotation: Quaternion.fromEulerDegrees(-90, 0, 0) // Point downward
})
LightSource.create(spotlight, {
type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
color: Color3.White(),
intensity: 16000
})- — full-brightness cone angle (degrees). Default
innerAngle. Min21.8, max0.179 - — outer fade angle (degrees). Default
outerAngle. Max30.179 - cannot exceed
innerAngle— if it does, the engine clamps them to the same value.outerAngle - The light direction follows the entity's forward vector (set via Transform rotation).
- is a discriminated union. To read/mutate spot params at runtime, narrow first:
typeif (comp.type?.$case === 'spot') { comp.type.spot.innerAngle = 30 }
沿指定方向发出锥形光:
typescript
import { Quaternion } from '@dcl/sdk/math'
const spotlight = engine.addEntity()
Transform.create(spotlight, {
position: Vector3.create(8, 4, 8),
rotation: Quaternion.fromEulerDegrees(-90, 0, 0) // Point downward
})
LightSource.create(spotlight, {
type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
color: Color3.White(),
intensity: 16000
})- ——达到完整亮度的锥角(度)。默认值为
innerAngle。最小值为21.8,最大值为0。179 - ——外侧渐隐角(度)。默认值为
outerAngle。最大值为30。179 - 不能大于
innerAngle;如果大于,引擎会将二者限制为相同值。outerAngle - 灯光方向遵循实体的前向向量(通过 Transform rotation 设置)。
- 是判别联合类型。如需在运行时读取或修改 Spot Light 参数,请先收窄类型:
typeif (comp.type?.$case === 'spot') { comp.type.spot.innerAngle = 30 }
Shadows
阴影
Enable shadows on point or spot lights:
typescript
LightSource.create(spotlight, {
type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
shadow: true,
intensity: 800
})Note: shadows are only rendered for spot lights, not point lights. is a top-level boolean on the component (not inside /).
shadowSpotPoint为 Point Light 或 Spot Light 启用阴影:
typescript
LightSource.create(spotlight, {
type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
shadow: true,
intensity: 800
})注意:只有 Spot Light 才会渲染阴影,Point Light 不会。 是组件顶层的布尔值(不在 / 内部)。
shadowSpotPointShadow Mask Textures (Gobos)
阴影遮罩纹理(Gobos)
Project a pattern through the light:
typescript
const maskedLight = LightSource.getMutable(spotlight)
maskedLight.shadowMaskTexture = Material.Texture.Common({
src: 'assets/Images/lightmask1.png'
})- Set to remove the mask again.
shadowMaskTexture = undefined - The mask projects light shape (e.g. a window pattern) — simulating caustics/soft shadows. Used on spot lights.
通过灯光投射图案:
typescript
const maskedLight = LightSource.getMutable(spotlight)
maskedLight.shadowMaskTexture = Material.Texture.Common({
src: 'assets/Images/lightmask1.png'
})- 将 设置为
shadowMaskTexture可再次移除遮罩。undefined - 遮罩用于投射灯光形状(例如窗户图案),模拟焦散或柔和阴影。适用于 Spot Light。
Toggling Lights
切换灯光
typescript
// Toggle on/off
const lightData = LightSource.getMutable(light)
lightData.active = !lightData.activetypescript
// Toggle on/off
const lightData = LightSource.getMutable(light)
lightData.active = !lightData.activeLight Limits
灯光限制
- A scene may create many lights (the engine test scene spawns ~9 across 2 parcels); the renderer decides how many render.
- Depending on the player's quality settings, between ~4 and ~10 lights render at once. If the scene has more than that, only the closest lights to the player are rendered.
- Up to ~3 shadow-casting lights render at once.
- The renderer auto-culls lights based on quality settings and proximity.
- Intensity is in candela (lumens/m² at 1m, i.e. lumens/4π). Default .
16000 - default is
range→ auto-computed as-1(fourth root, in meters). Set an explicitintensity^0.25to override — this also limits a light's influence and saves performance.range - Spread lights out so few are near the player at once (only the closest ones render).
- 场景可以创建许多灯光(引擎测试场景在 2 个 parcel 中生成了约 9 个);具体渲染多少个由渲染器决定。
- 根据玩家的质量设置,每次会同时渲染约 4~10 个灯光。如果场景中的灯光更多,则只渲染距离玩家最近的灯光。
- 每次最多同时渲染约 3 个投射阴影的灯光。
- 渲染器会根据质量设置和距离自动剔除灯光。
- 强度以坎德拉为单位(1 米处的 lumens/m²,即 lumens/4π)。默认值为 。
16000 - 的默认值为
range,此时会根据-1自动计算(四次方根,单位为米)。设置明确的intensity^0.25可覆盖自动计算结果,同时也能限制灯光的影响范围并节省性能。range - 应将灯光分散布置,使玩家附近同时只有少量灯光(只有距离最近的灯光会被渲染)。
SkyboxTime (Day/Night Cycle)
SkyboxTime(昼夜循环)
Use SkyboxTime for atmosphere — nighttime scenes with point lights create dramatic environments.
使用 SkyboxTime 营造环境氛围——夜景场景结合 Point Light 可以营造富有戏剧性的效果。
Fixed Time in scene.json
在 scene.json 中固定时间
Set a permanent time of day without code. Two valid locations:
json
// Genesis City scene — top-level
{ "skyboxConfig": { "fixedTime": 43200 } }
// World — inside worldConfiguration
{ "worldConfiguration": { "name": "my-name.dcl.eth", "skyboxConfig": { "fixedTime": 36000 } } }Time values (seconds since midnight, full day = 86400): 0 = midnight, 21600 = 6 AM, 43200 = noon, 64800 = 6 PM (dusk), 86400 = full day.
Precedence (verified against the engine test scenes): wins over top-level ; either JSON value is in turn overridden at runtime by a component on .
worldConfiguration.skyboxConfig.fixedTimeskyboxConfig.fixedTimeSkyboxTimeengine.RootEntity无需编写代码即可设置固定的每日时刻。有两个有效位置:
json
// Genesis City scene — top-level
{ "skyboxConfig": { "fixedTime": 43200 } }
// World — inside worldConfiguration
{ "worldConfiguration": { "name": "my-name.dcl.eth", "skyboxConfig": { "fixedTime": 36000 } } }时间值的单位为距午夜的秒数,一整天为 86400 秒:0 表示午夜,21600 表示上午 6 点,43200 表示正午,64800 表示下午 6 点(黄昏),86400 表示一整天。
优先级(已根据引擎测试场景验证): 的优先级高于顶层的 ;运行时,实体 上的 组件又会覆盖这两个 JSON 值。
worldConfiguration.skyboxConfig.fixedTimeskyboxConfig.fixedTimeengine.RootEntitySkyboxTimeRead Current World Time
读取当前世界时间
typescript
import { getWorldTime } from '~system/Runtime'
executeTask(async () => {
const time = await getWorldTime({})
console.log('Seconds since midnight:', time.seconds)
})typescript
import { getWorldTime } from '~system/Runtime'
executeTask(async () => {
const time = await getWorldTime({})
console.log('Seconds since midnight:', time.seconds)
})Change Time Dynamically
动态更改时间
typescript
import { engine, SkyboxTime, TransitionMode } from '@dcl/sdk/ecs'
// Set time of day (must target the root entity)
SkyboxTime.create(engine.RootEntity, { fixedTime: 43200 }) // Noon
// Change with transition direction
SkyboxTime.createOrReplace(engine.RootEntity, {
fixedTime: 64800, // Dusk (6 PM)
transitionMode: TransitionMode.TM_BACKWARD // TM_FORWARD (0, default) or TM_BACKWARD (1)
})
// Remove the component to hand control back to global/world time
SkyboxTime.deleteFrom(engine.RootEntity)- (optional) sets the animation direction when the time changes. Default
transitionMode.TM_FORWARD - The component must live on . Deleting it reverts to the scene.json/world time (or the global day/night cycle).
engine.RootEntity
typescript
import { engine, SkyboxTime, TransitionMode } from '@dcl/sdk/ecs'
// Set time of day (must target the root entity)
SkyboxTime.create(engine.RootEntity, { fixedTime: 43200 }) // Noon
// Change with transition direction
SkyboxTime.createOrReplace(engine.RootEntity, {
fixedTime: 64800, // Dusk (6 PM)
transitionMode: TransitionMode.TM_BACKWARD // TM_FORWARD (0, default) or TM_BACKWARD (1)
})
// Remove the component to hand control back to global/world time
SkyboxTime.deleteFrom(engine.RootEntity)- (可选)用于设置时间变化时的动画方向。默认值为
transitionMode。TM_FORWARD - 该组件必须位于 上。删除组件后,将恢复使用 scene.json/world 中的时间(或全局昼夜循环)。
engine.RootEntity
Day/Night Cycle System
昼夜循环系统
typescript
let currentTime = 43200
const CYCLE_SPEED = 100 // Time units per second
function dayNightCycle(dt: number) {
currentTime = (currentTime + CYCLE_SPEED * dt) % 86400
SkyboxTime.createOrReplace(engine.RootEntity, {
fixedTime: currentTime
})
}
engine.addSystem(dayNightCycle)typescript
let currentTime = 43200
const CYCLE_SPEED = 100 // Time units per second
function dayNightCycle(dt: number) {
currentTime = (currentTime + CYCLE_SPEED * dt) % 86400
SkyboxTime.createOrReplace(engine.RootEntity, {
fixedTime: currentTime
})
}
engine.addSystem(dayNightCycle)Realm Info
Realm 信息
Detect which realm (server) the player is connected to:
typescript
import { getRealm } from '~system/Runtime'
executeTask(async () => {
const realm = await getRealm({})
console.log('Realm:', realm.realmInfo?.realmName)
console.log('Network:', realm.realmInfo?.networkId)
console.log('Base URL:', realm.realmInfo?.baseUrl)
})检测玩家当前连接到的 realm(服务器):
typescript
import { getRealm } from '~system/Runtime'
executeTask(async () => {
const realm = await getRealm({})
console.log('Realm:', realm.realmInfo?.realmName)
console.log('Network:', realm.realmInfo?.networkId)
console.log('Base URL:', realm.realmInfo?.baseUrl)
})Emissive Materials (Glow Effects)
自发光材质(辉光效果)
For a visual glow without casting light on surroundings:
typescript
import { engine, Material } from '@dcl/sdk/ecs'
import { Color4, Color3 } from '@dcl/sdk/math'
// Self-illuminated material (emissiveColor uses Color3, not Color4)
Material.setPbrMaterial(entity, {
albedoColor: Color4.create(0, 0, 0, 1),
emissiveColor: Color3.create(0, 1, 0), // Green glow
emissiveIntensity: 2.0
})Note: emissive materials don't illuminate other surrounding entities, they just have a glow effect on them.
如果只需产生视觉辉光效果,而不会向周围投射光线,可以使用以下方式:
typescript
import { engine, Material } from '@dcl/sdk/ecs'
import { Color4, Color3 } from '@dcl/sdk/math'
// Self-illuminated material (emissiveColor uses Color3, not Color4)
Material.setPbrMaterial(entity, {
albedoColor: Color4.create(0, 0, 0, 1),
emissiveColor: Color3.create(0, 1, 0), // Green glow
emissiveIntensity: 2.0
})注意:自发光材质不会照亮周围的其他实体,只会在自身产生辉光效果。
Combining Emissive + LightSource
结合自发光材质与 LightSource
For an object that both glows visually and casts light:
typescript
// Visual glow on the mesh
Material.setPbrMaterial(bulb, {
emissiveColor: Color3.create(1, 0.9, 0.7),
emissiveIntensity: 1.5
})
// Actual light emission
LightSource.create(bulb, {
type: LightSource.Type.Point({}),
color: Color3.create(1, 0.9, 0.7),
intensity: 200,
range: 10
})如果对象既需要视觉辉光,又需要实际投射光线:
typescript
// Visual glow on the mesh
Material.setPbrMaterial(bulb, {
emissiveColor: Color3.create(1, 0.9, 0.7),
emissiveIntensity: 1.5
})
// Actual light emission
LightSource.create(bulb, {
type: LightSource.Type.Point({}),
color: Color3.create(1, 0.9, 0.7),
intensity: 200,
range: 10
})Shadow Quality
阴影质量
shadowfalseSpot({...})innerAngle?outerAngle?typescript
import { LightSource } from '@dcl/sdk/ecs'
// Spot light with shadows enabled
LightSource.create(spotEntity, {
type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
shadow: true, // top-level boolean
intensity: 800
})Constraints:
- Shadows are only supported for spot lights; point lights do not cast shadows.
- Max 3 shadow-casting lights rendered at a time — disable on lights that don't need it. Spot lights with shadows suit dramatic effects such as flashlights.
shadow - Shadow quality/culling is automatic, based on the light's distance from the player. Exact distances vary by light type and the player's quality settings; general rule:
| Distance from player | Result |
|---|---|
| < 10 m | Soft shadows (high quality) |
| 10–20 m | Hard shadows (low quality) |
| > 20 m | No shadows rendered |
- The light itself keeps illuminating at much larger distances — it is only disabled when the player is more than 160 m away (10 parcels). This makes LightSource suitable for large-scale setups like stage lighting at live events, where most of the audience is far from the fixtures.
- Lights only render while the player is standing inside the scene; outside, they are not rendered.
Need advanced material effects? See the advanced-rendering skill for metallic, roughness, transparency, texture maps, texture tweens, and texture modes.
shadowfalseSpot({...})innerAngle?outerAngle?typescript
import { LightSource } from '@dcl/sdk/ecs'
// Spot light with shadows enabled
LightSource.create(spotEntity, {
type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
shadow: true, // top-level boolean
intensity: 800
})限制:
- 只有 Spot Light 支持阴影;Point Light 不会投射阴影。
- 每次最多渲染 3 个投射阴影的灯光——请关闭不需要阴影的灯光上的 。带阴影的 Spot Light 适合手电筒等富有戏剧性的效果。
shadow - 阴影质量和剔除是自动完成的,取决于灯光与玩家之间的距离。具体距离因灯光类型和玩家质量设置而异;一般规则如下:
| 与玩家的距离 | 结果 |
|---|---|
| < 10 m | 柔和阴影(高质量) |
| 10–20 m | 硬阴影(低质量) |
| > 20 m | 不渲染阴影 |
- 灯光本身在更远的距离上仍会继续照亮物体——只有当玩家距离超过 **160 m(10 个 parcel)**时才会禁用。这使 LightSource 适合现场活动舞台灯光等大规模场景,因为大多数观众都离灯具很远。
- 只有当玩家位于场景内部时才会渲染灯光;在场景外部时不会渲染。
需要高级材质效果? 有关 metallic、roughness、透明度、纹理贴图、纹理渐变和纹理模式,请参阅 advanced-rendering skill。
Gotchas
常见问题
- left unset (
range) is auto-derived from intensity as-1— small intensities give surprisingly short range. Setintensity^0.25explicitly for predictable falloff.range - only affects spot lights; setting it on a point light has no effect.
shadow - Animating a light's direction: put a /
Tween(Rotate mode) on the light entity — the beam follows the entity's forward vector.TweenSequence - on
SkyboxTimeoverrides any scene.jsonRootEntity;fixedTimereverts to it.deleteFrom
- 如果不设置 (保持为
range),系统会根据强度自动推导出-1——较小的强度可能会产生短得出乎意料的作用范围。请明确设置intensity^0.25,以获得可预测的衰减效果。range - 只对 Spot Light 生效;在 Point Light 上设置它不会产生任何效果。
shadow - 为灯光制作方向动画:在灯光实体上添加 /
Tween(Rotate 模式)——光束会跟随实体的前向向量。TweenSequence - 上的
RootEntity会覆盖 scene.json 中的任何SkyboxTime;调用fixedTime后则会恢复使用该配置。deleteFrom
Example scenes
示例场景
Engine-team test scenes (real API, exercised against the engine):
- https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/0,4-dynamic-lights — point & spot LightSource: toggle active, color, range, intensity, spot inner/outer angle at runtime, shadow-mask (gobo) swapping, and tweened light rotation.
- https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/2,0-skybox-scene-json — fixed skybox time via top-level ; reads it back with
skyboxConfig.fixedTime.getSceneInformation - https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/3,0-skybox-world-json — fixed skybox time via (World variant); demonstrates the worldConfiguration-wins precedence.
worldConfiguration.skyboxConfig.fixedTime - https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/2,1-skybox-sdk-scene-a and https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/3,1-skybox-sdk-scene-b — runtime on
SkyboxTimewithRootEntity, plusTransitionModeto return to global time.deleteFrom
引擎团队测试场景(使用真实 API,并已针对引擎进行验证):
- https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/0,4-dynamic-lights —— Point Light 与 Spot Light 的 LightSource:运行时切换 active、color、range、intensity 以及 Spot Light 的 inner/outer angle,切换 shadow mask(gobo),并通过 Tween 实现灯光旋转。
- https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/2,0-skybox-scene-json —— 通过顶层 固定天空盒时间;使用
skyboxConfig.fixedTime读取该值。getSceneInformation - https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/3,0-skybox-world-json —— 通过 固定天空盒时间(World 变体);演示 worldConfiguration 优先级更高的规则。
worldConfiguration.skyboxConfig.fixedTime - https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/2,1-skybox-sdk-scene-a 和 https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/3,1-skybox-sdk-scene-b —— 在 上运行时使用带
RootEntity的TransitionMode,并通过SkyboxTime恢复为全局时间。deleteFrom