RectAreaLight
是矩形面光源,光源类似一个平面,整个面会均匀的发光,这种光源可以用来模拟明亮的窗户,和发光的条状照明灯。
示例:https://ithanmang.gitee.io/threejs/home/201808/20180801/02-RectAreaLight.html
使用矩形面光源,需要注意以下事项
RectAreaLight
光源不支持阴影效果。MeshStandardMaterial
和MeshPhysicalMaterial
会被支持。RectAreaLightUniformsLib
js 库文件,到场景中,否则不会产生反光效果。<!--注意:使用RectAreaLight 必须包含这个js库文件-->
<script src="../../libs/examples/js/lights/RectAreaLightUniformsLib.js"></script>
RectAreaLight( color : Integer, intensity : Float, width : Float, height : Float )
color - (可选) 光的颜色. 默认是 0xffffff
(white).
intensity - (可选) 光的强度或者亮度. 默认为1
.
width - (可选) 光面的宽度,默认为10
.
height - (可选) 光面的高度,默认为10
.
示例中创建了一个矩形面光源
// 实例化矩形面光源,10 * 10 光源强度为1
rectLight = new THREE.RectAreaLight(0xffffff, 1, 10, 10);
rectLight.position.set(5, 6, 0);
scene.add(rectLight);
并且创建了一个矩形网格对象,将矩形面光源与矩形网格绑定
// 创建矩形网格,便于操作和测试
rectLightMesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(), new THREE.MeshBasicMaterial());
rectLightMesh.scale.x = rectLight.width;
rectLightMesh.scale.y = rectLight.height;
// 将矩形面光源与 plane 绑定
rectLight.add(rectLightMesh);
创建矩形面光源的背面
let rectLightMeshBack = new THREE.Mesh(new THREE.PlaneBufferGeometry(), new THREE.MeshBasicMaterial({color: 0x808080}));
// 绕 y 轴旋转180度,形成与面光源的背面效果
rectLightMeshBack.rotation.y = Math.PI;
rectLightMesh.add(rectLightMeshBack);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RectAreaLight 矩形平面光源</title>
<style>
body {
margin: 0;
overflow: hidden; /*溢出隐藏*/
}
</style>
<script src="../../libs/build/three.min.js"></script>
<script src="../../libs/examples/js/controls/OrbitControls.js"></script>
<script src="../../libs/examples/js/libs/dat.gui.min.js"></script>
<script src="../../libs/examples/js/libs/stats.min.js"></script>
<script src="../../libs/examples/js/Detector.js"></script>
<!--注意:使用RectAreaLight 必须包含这个js库文件-->
<script src="../../libs/examples/js/lights/RectAreaLightUniformsLib.js"></script>
</head>
<body>
<script>
let stats = initStats();
let scene, camera, renderer, rectLight, rectLightMesh, controls, guiControls;
let floor;
let origin = new THREE.Vector3(0, 0, 0);
// 场景
function initScene() {
scene = new THREE.Scene();
}
// 相机
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 5000);
camera.position.set(0, 20, 40);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
// 渲染器
function initRenderer() {
renderer = new THREE.WebGLRenderer({antialias: true});
// 设置渲染器的像素比例,按照设备
renderer.setPixelRatio(window.devicePixelRatio);
// 渲染范围
renderer.setSize(window.innerWidth, window.innerHeight);
// 开启阴影支持
renderer.shadowMap.enabled = true;
// 阴影类型
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// 将渲染器添加到文档
document.body.appendChild(renderer.domElement);
}
let ambient;
// 灯光
function initLight() {
ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient);
// 实例化矩形面光源,10 * 10 光源强度为1
rectLight = new THREE.RectAreaLight(0xffffff, 1, 10, 10);
rectLight.position.set(5, 6, 0);
scene.add(rectLight);
// 创建矩形网格,便于操作和测试
rectLightMesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(), new THREE.MeshBasicMaterial());
rectLightMesh.scale.x = rectLight.width;
rectLightMesh.scale.y = rectLight.height;
// 将矩形面光源与 plane 绑定
rectLight.add(rectLightMesh);
let rectLightMeshBack = new THREE.Mesh(new THREE.PlaneBufferGeometry(), new THREE.MeshBasicMaterial({color: 0x808080}));
// 绕 y 轴旋转180度,形成与面光源的背面效果
rectLightMeshBack.rotation.y = Math.PI;
rectLightMesh.add(rectLightMeshBack);
}
// 控制器
function initControls() {
controls = new THREE.OrbitControls(camera, renderer.domElement);
// 添加惯性
controls.enableDamping = true;
// 最大偏移角度
controls.maxPolarAngle = 0.49 * Math.PI;
// 旋转速度
controls.rotateSpeed = 0.05;
}
// 调试插件
function initGui() {
guiControls = new function () {
this.ambientLight = ambient.color.getStyle();
this.ambientIntensity = ambient.intensity;
this.motion = true;
this.width = rectLight.width;
this.height = rectLight.height;
this.color = rectLight.color.getStyle();
this.intensity = rectLight.intensity;
this.floorColor = floor.material.color.getStyle();
this.floorRoughness = floor.material.roughness;
this.floorMetalness = floor.material.metalness;
this.color = standMaterial.color.getStyle();
this.roughness = standMaterial.roughness;
this.metalness = standMaterial.metalness;
};
let gui = new dat.GUI({width: 300});/*这是插件的宽度*/
gui.add(guiControls, 'motion');
let ambientFolder = gui.addFolder('环境光');
ambientFolder.addColor(guiControls, 'ambientLight').onChange(function (e) {
ambient.color.setStyle(e);
});
ambientFolder.add(guiControls,'ambientIntensity',0, 1).onChange(function (e) {
ambient.intensity = e;
});
ambientFolder.open();
let lightFolder = gui.addFolder('矩形面光');
lightFolder.add(guiControls, 'width', 0, 20).onChange(function (e) {
rectLight.width = e;
rectLightMesh.scale.x = rectLight.width;
});
lightFolder.add(guiControls, 'height', 0, 20).onChange(function (e) {
rectLight.height = e;
rectLightMesh.scale.y = rectLight.height;
});
lightFolder.addColor(guiControls, 'color').onChange(function (e) {
rectLight.color = new THREE.Color(e);
rectLightMesh.material.color.copy(rectLight.color);
});
lightFolder.add(guiControls, 'intensity',0 ,5).onChange(function (e) {
rectLight.intensity = e;
});
lightFolder.open();
let floorFolder = gui.addFolder('地板');
floorFolder.addColor(guiControls, 'floorColor').onChange(function (e) {
floor.material.color.setStyle(e);
});
floorFolder.add(guiControls,'floorRoughness',0, 1).onChange(function (e) {
floor.material.roughness = e;
});
floorFolder.add(guiControls,'floorMetalness',0,1).onChange(function (e) {
floor.material.metalness = e;
});
floorFolder.open();
let standFolder = gui.addFolder('标准材质');
standFolder.addColor(guiControls,'color').onChange(function (e) {
standMaterial.color.setStyle(e);
});
standFolder.add(guiControls,'roughness',0,1).onChange(function (e) {
standMaterial.roughness = e;
});
standFolder.add(guiControls,'metalness',0,1).onChange(function (e) {
standMaterial.metalness = e;
});
standFolder.open();
}
let standMaterial;
// 场景中的内容
function initContent() {
// 地板
let floorGeometry = new THREE.BoxBufferGeometry(2000, 1, 2000);
// 使用矩形平明光源,必须使用 MeshStandarMaterial 或者 MeshPhysicalMaterial,来实现反射效果
let floorMaterial = new THREE.MeshStandardMaterial({color: 0x636363, roughness: 0, metalness: 0});
floor = new THREE.Mesh(floorGeometry, floorMaterial);
scene.add(floor);
standMaterial = new THREE.MeshStandardMaterial({color: 0xA00000, roughness: 0, metalness: 0});
// 立方体
let cubeGeometry = new THREE.BoxBufferGeometry(4, 4, 4);
let cube = new THREE.Mesh(cubeGeometry, standMaterial);
cube.position.set(-5, 2, 0);
scene.add(cube);
// 球体
let sphereGeometry = new THREE.SphereBufferGeometry(2, 50, 50);
let sphere = new THREE.Mesh(sphereGeometry, standMaterial);
sphere.position.set(0, 3, 0);
scene.add(sphere);
// 圆桶体
let cylinderGeometry = new THREE.TorusBufferGeometry(2, 0.3, 50, 50);
let cylinder = new THREE.Mesh(cylinderGeometry, standMaterial);
cylinder.rotation.x = -0.5 * Math.PI;
cylinder.position.set(5, 2, 0);
scene.add(cylinder);
}
// 性能插件
function initStats() {
let stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
return stats;
}
// 更新
function update() {
stats.update();
controls.update();
// guiControls.motion 为true 的时候会一直旋转
if (guiControls.motion){
let time = (Date.now() / 2000);
let lx = 15.0 * Math.cos( time );
let lz = 15.0 * Math.sin( time );
let ly = 5.0 + 5.0 * Math.sin( time / 3.0 );
rectLight.position.set(lx, ly, lz);
rectLight.lookAt(origin);
}
}
// 初始化
function init() {
// 兼容性判断,若不兼容会提示信息
if (!Detector.webgl) Detector.addGetWebGLMessage();
initScene();
initCamera();
initRenderer();
initLight();
initControls();
initContent();
initGui();
window.addEventListener('resize', onWindowResize, false);
}
// 窗口变动触发的方法
function onWindowResize() {
// 重新设置相机的宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 更新相机投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器大小
renderer.setSize(window.innerWidth, window.innerHeight);
}
// 循环渲染
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
update();
}
// 页面绘制完后加载
window.onload = function () {
init();
animate();
};
</script>
</body>
</html>