【Threejs-sdk】使用 mogl.js 创建灯光与Hdr:Lighting HDR
使用 mogl.js 配置灯光:Lighting
github 欢迎加开源
本教程基于示例 packages/examples/src/views/examples/Lighting.vue,带你用 mogl.js 快速完成常见灯光场景的搭建与调参:环境光、平行光、点光源、聚光灯,以及“日光/夕阳/夜晚/工作室”等预设方案。
你将学到
- 如何用 scene.light API 一行代码添加多种灯光
- 如何动态调整灯光的颜色/强度/位置/角度等属性
- 如何启用阴影(并让网格/地面/模型正确投射与接收阴影)
- 如何快速切换常见灯光预设
核心概念速览(mogl.js)
- scene.light:灯光管理器,提供 addAmbient/addDirectional/addPoint/addSpot 等便捷方法
- scene.renderer:渲染器管理,支持一键开启阴影与窗口自适应
- 组合式对象:保留灯光实例引用,便于后续动态修改属性
1. 创建场景并开启基础能力
import { Scene } from '@w3d/core';const scene = new Scene(container, {renderer: { antialias: true, outputColorSpace: 'srgb' },camera: { fov: 45, position: [10, 8, 15], lookAt: [0, 0, 0] }
});
scene.init();// 推荐:开启阴影 + 窗口自适应
scene.renderer.enableShadow(true);
scene.renderer.enableResize();
阴影要生效,除灯光外,还需给 mesh 设置 castShadow/receiveShadow(见第 3 节)。
2. 添加灯光与Hdr:一行一个方法
import { HDRLoader } from '@w3d/components';
// 1) 环境光:均匀照亮,提供基础亮度
const ambient = scene.light.addAmbient({ color: '#ffffff', intensity: 0.4 });// 2) 平行光:模拟太阳光,可投射阴影
const directional = scene.light.addDirectional({color: '#ffffff',intensity: 1.0,position: [10, 10, 5],castShadow: true,shadowMapSize: 2048
});// 3) 点光源:从一点向四周发散,随距离衰减
const point = scene.light.addPoint({color: '#ff6b6b',intensity: 1.0,position: [5, 8, 5],distance: 20,decay: 2
});// 4) 聚光灯:锥形光束,带角度/边缘模糊
const spot = scene.light.addSpot({color: '#4ecdc4',intensity: 1.0,position: [-5, 10, 5],target: [0, 0, 0],angle: Math.PI / 6,penumbra: 0.1,distance: 30,decay: 2
});const hdr = await scene.add('HDRLoader', {name: 'environment',url: '/textures/blouberg_sunrise_2_1k.hdr',intensity: 1.0
});
提示:环境光常与其它光源组合;平行光适合“太阳”效果;点光源有距离衰减;聚光灯可突出焦点对象。
3. 阴影准备(地面/模型)
import * as THREE from 'three';
const plane = new THREE.Mesh(new THREE.PlaneGeometry(20, 20),new THREE.MeshLambertMaterial({ color: '#cccccc' })
);
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
scene.scene.add(plane);const sphere = new THREE.Mesh(new THREE.SphereGeometry(1.5, 32, 32),new THREE.MeshPhongMaterial({ color: '#ff6b6b' })
);
sphere.position.set(-3, 1.5, 0);
sphere.castShadow = sphere.receiveShadow = true;
scene.scene.add(sphere);const cube = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2),new THREE.MeshPhongMaterial({ color: '#4ecdc4' })
);
cube.position.set(3, 1, 0);
cube.castShadow = cube.receiveShadow = true;
scene.scene.add(cube);
4. 动态修改灯光
ambient.color.setHex('#ffffff'.replace('#', '0x'));
ambient.intensity = 0.6;
directional.position.set(10, 12, 6);
directional.castShadow = true;
point.position.set(6, 8, 6);
point.distance = 24;
point.decay = 2;
spot.angle = Math.PI / 4;
spot.penumbra = 0.2;
5. 预设切换
function setDaylight() {scene.light.removeAll();scene.light.addAmbient({ color: '#87CEEB', intensity: 0.6 });scene.light.addDirectional({color: '#FFF8DC',intensity: 1.2,position: [10, 20, 10],castShadow: true});
}
function setNight() {scene.light.removeAll();scene.light.addAmbient({ color: '#191970', intensity: 0.2 });scene.light.addPoint({ color: '#FFD700', intensity: 2.0, position: [0, 10, 0], distance: 25 });
}
function setStudio() {scene.light.removeAll();scene.light.addAmbient({ color: '#ffffff', intensity: 0.3 });scene.light.addDirectional({color: '#ffffff',intensity: 1.0,position: [10, 10, 10],castShadow: true});scene.light.addDirectional({ color: '#ffffff', intensity: 0.5, position: [-10, 5, -5] });
}
6. 启动与清理
scene.start();
scene.dispose();
提示/FAQ:
- 阴影需:enableShadow(true) + 灯光 castShadow + mesh 的 castShadow/receiveShadow + 支持阴影的材质 + 至少一个接收阴影的表面。
- 颜色赋值可用
setHex(color.replace('#','0x'))
或 THREE.Color;避免直接传字符串。 - 通过统一数据源(如 reactive 状态)更新 position/强度等,避免 UI 与场景不同步。