three.js常见灯光的使用
环境光(AmbientLight) 点光源(PointLight) 聚光灯(SpotLight) 平行光(DirectinalLight)
<!DOCTYPE html>
<html lang="en">
<head>
<title>threeJS常见灯光</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<!--引入three.js三维引擎-->
<script src="three.js"></script>
<script src="OrbitControls.js"></script>
<link rel="stylesheet" href="main.css">
</head>
<body>
<script>
// 场景, 相机, 渲染器
var scene, camera, renderer;
var pointLight, // 点光源,
spotLight, // 聚光灯,
lightHelper, // 模拟聚光灯,
directionLight, // 平行光,
shadowCameraHelper; // 模拟相机视锥体
function init() {
/**
* 创建场景
*/
scene = new THREE.Scene();
/**
* 创建透视相机对象
*/
camera = new THREE.PerspectiveCamera(
35, // fov — 摄像机视锥体垂直视野角度
window.innerWidth / window.innerHeight, // 长宽比
1, // 摄像机视锥体近端面
1000 // 摄像机视锥体远端面
);
// 设置相机位置
camera.position.set( 65, 8, - 10 );
/**
* 创建渲染器
*/
renderer = new THREE.WebGLRenderer();
// 设置分辨率为当前设备的分辨率,解决场景模糊,抗锯齿的一-种很好的方法
renderer.setPixelRatio( window.devicePixelRatio );
// 设置渲染区域尺寸 宽高
renderer.setSize( window.innerWidth, window.innerHeight );
// 在body元素中插入canvas对象
document.body.appendChild( renderer.domElement );
// 告诉render我们需要阴影(允许阴影隐射)
renderer.shadowMap.enabled = true;
// 使用PCF算法来过滤阴影映射
//https://threejs.org/docs/index.html?q=WebGLRenderer#api/zh/constants/Renderer
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// 默认为 false. 如果设置了该参数,表示所有纹理和颜色应当使用预乘的gamma值来输入
renderer.gammaInput = true;
// 默认为 false. 如果设置了该参数,表示所有纹理和颜色应当使用预乘的gamma值来输出。
renderer.gammaOutput = true;
/**
* 创建轨道控制器,实现用鼠标交互 旋转、平移,缩放
* 关于OrbitControls轨道控制器的使用说明
* http://www.yanhuangxueyuan.com/doc/Three.js/OrbitControls.html
*/
var controls = new THREE.OrbitControls( camera, renderer.domElement );
// 当鼠标移动时调用render方法
controls.addEventListener( 'change', render );
// 视角最小距离
controls.minDistance = 1;
// 视角最远距离
controls.maxDistance = 500;
// 禁止右键拖拽
controls.enablePan = false;
/**
* * 环境光
* 笼罩在整个空间无处不在的光,环境光可以说是场景的整体基调,由于环境光无处不在,
* 也就是说环境光是没有方向的,不能产生阴影。
* 也不能作为环境中唯一的光源。否则后果就是所有的物体都是黑的
* 具体作用就是弱化阴影或者给场景添加一些颜色,所以设置的时候只需要设置一些颜色即可
*/
var ambient = new THREE.AmbientLight(
0xffffff, // 颜色的rgb数值,不填默认0xffffff
0.1 // 光照的强度。缺省值为 1
);
// 将环境光添加到场景中
scene.add( ambient );
/**
* * 点光源
* 点光源即向四面八方发射的单点光源,可以将点光源想象成萤火虫一样发出的光。
* 由于它白的光线也发射到四面八方, 不能产生阴影
* 原因是这样的光源会朝着所有的方向发射光线,
* 在这种情况下计算阴影对GPU来讲是一个非常沉重的负担,所以不能产生阴影
* 如果需要阴影可以使用 比如聚光灯SpotLight
*/
pointLight = new THREE.PointLight(
0xffffff, // 光照颜色,默认 0xffffff
1 // 光照强度, 光照强度 默认 1
);
// 设置光源位置
pointLight.position.set( 15, 40, 35 );
// 从光源到光照强度为0的位置。当设置为0时,光永远不会消失(距离无穷大)
pointLight.distance = 200;
// 是否开启点光源
pointLight.visible=true;
// 将点光源添加到场景中
scene.add( pointLight );
/**
* 聚光灯
* 锥形效果的光源, 能够产生阴影
*/
spotLight = new THREE.SpotLight( 0xffffff, 1 );
// 设置聚光灯的位置
spotLight.position.set( 15, 40, 35 );
// 光线散射角度, 最大为Math.PI/2
spotLight.angle = Math.PI / 4;
// 聚光锥的半影衰减百分比。在0和1之间的值。 默认值 — 0.0。
spotLight.penumbra = 0.05; //半影
// 沿着光照距离的衰减量 设置为等于2将实现现实世界的光衰减 默认1
spotLight.decay = 2; //衰落
// 如果非零,那么光强度将会从最大值当前灯光位置处按照距离线性衰减到0. 默认为0.0
spotLight.distance = 200;
// 此属性设置为 true 聚光灯将投射阴影。
// 警告: 这样做的代价比较高而且需要一直调整到阴影看起来正确。
// 不是所有的光源都可以投射阴影,这里使用聚点光源可以产生阴影
spotLight.castShadow = true;
// 将聚光灯添加到场景中
scene.add( spotLight );
/**
* 平行光
* 平行光,类似太阳光,距离很远的光,如太阳般,照射到地球上每一束光都是平行行的。
* 所有对象接收的光强都是一样的,会产生阴影,与聚点光源的主要差别是:
* 聚点光源光距离目标越远光越暗淡,而平行光光强都是一样样的。
* 用direction(方向),color(颜色),intensity(强度)来计算属性和阴影,
* 形成的不是光锥而是一个方块,很重要
*/
directionLight=new THREE.DirectionalLight(
0xffffff, // 光的颜色 默认0xffffff
1 // 光照的强度 默认1
);
// 平行光的位置
directionLight.position.set( 15, 40, 35 );
// 如果设置为 true 该平行光会产生动态阴影。
directionLight.castShadow = true;
// 如果非零,那么光强度将会从最大值当前灯光位置处按照距离线性衰减到0。 缺省值为 0.0
directionLight.distance = 200;
// 将平行光添加到场景中
scene.add( directionLight );
// 用于模拟聚光灯 SpotLight 的锥形辅助对象.
lightHelper = new THREE.SpotLightHelper( spotLight );
// 将模拟聚光灯辅助对象添加到场景中
scene.add( lightHelper );
// 用于模拟相机视锥体的辅助对象. 用来模拟相机视锥体
shadowCameraHelper = new THREE.CameraHelper( spotLight.shadow.camera );
// 将相机视锥体的辅助对象添加到场景中
scene.add( shadowCameraHelper );
// 用于简单模拟3个坐标轴的对象. 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
scene.add( new THREE.AxesHelper( 10 ) );
// 创建具有镜面高光的光泽表面的材质
// 颜色 0xffffff dithering 是否对颜色应用抖动以消除条带的外观
var material = new THREE.MeshPhongMaterial( {
color: 0x808080,
dithering: true
} );
// 创建一个缓冲平面 长宽
var geometry = new THREE.PlaneBufferGeometry( 300, 300 );
// 创建网格对象 物体 材质
var mesh = new THREE.Mesh( geometry, material );
// 设置网格对象的位置
mesh.position.set( 0, - 1, 0 );
// 沿着X轴旋转
mesh.rotation.x = - Math.PI * 0.5;
// 接受阴影
mesh.receiveShadow = true;
// 将网格对象添加到场景中
scene.add( mesh );
// 创建具有镜面高光的光泽表面的材质 颜色 0xffffff
// dithering 是否对颜色应用抖动以消除条带的外观
var material = new THREE.MeshPhongMaterial( {
color: 0x4080ff,
dithering: true
} );
// 创建一个长方体
var geometry = new THREE.BoxBufferGeometry( 3, 1, 2 );
// 创建网格对象 物体 材质
var mesh = new THREE.Mesh( geometry, material );
// 设置网格对象的位置
mesh.position.set( 40, 2, 0 );
// cast投射,就是允许方块投射阴影
mesh.castShadow = true;
// 将网格对象添加到场景中
scene.add( mesh );
// 平行光的方向是从它的位置到目标位置。默认的目标位置为原点 (0,0,0)
directionLight.target = mesh;
// 轨道控制器的方向拷贝mesh的位置
controls.target.copy( mesh.position );
// 更新控制器。必须在摄像机的变换发生任何手动改变后调用
controls.update();
// 当浏览器发生改变时
window.addEventListener( 'resize', onResize, false );
}
function onResize() {
// 摄像机视锥体的长宽比,通常是使用画布的宽/画布的高。默认值是1 (正方形画布)
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机投影矩阵。在任何参数被改变以后必须被调用
camera.updateProjectionMatrix();
// 将输出canvas的大小调整为(width, height)并考虑设备像素比
// 且将视口从(0, 0)开始调整到适合大小
renderer.setSize( window.innerWidth, window.innerHeight );
}
function render() { // 一上来调用 鼠标移动调用
// 更新聚光灯辅助对象
lightHelper.update();
// 基于相机的投影矩阵更新辅助对象
shadowCameraHelper.update();
// 用相机(camera)渲染一个场景(scene)
renderer.render( scene, camera );
}
init();
render();
</script>
</body>
</html>