文章目录
- 简介
- 分类
- 环境光
- 点光源
- 平行光
- 聚光灯
- 光源辅助对象
- 相关计算
- 颜色计算
- 阴影
- 相关属性
- castShadow
- receiveShadow
- shadow
- LightShadow
- 基类
专栏目录请点击
简介
光源是对于自然界光照的模拟,往往为了更好的渲染场景,需要设置不同的光源,设置不同的光照强度
分类
一般光源可以分成以下类别
- 环境光(AmbientLight)
- 平行光(DirectionalLight)
- 点光源(PointLight)
- 聚光灯光源(SpotLight)
环境光
环境光是没有特定方向的光源,主要是均匀改变物体明暗的效果,如果没有设置环境光,那么物体会是一个全黑的对象
- 没有环境光
- 有环境光
//环境光:环境光颜色RGB成分分别和物体材质颜色RGB成分分别相乘
var ambient = new THREE.AmbientLight(0x888888);
scene.add(ambient);//环境光对象添加到scene场景中
当环境光打上之后,物体立马改变了颜色
点光源
- 点光源就像我们生活中的灯泡,当设置点光源的时候,必须设置光源的位置属性
position
- 他会呈现出阴暗面,我们可以设置光源的位置来感受点光源的特点
var point = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300);
scene.add(point);
3. 我们修改点光源的位置,看一下他的渲染效果
point.position.set(-400, -200, -300);
我们拖动一下物体就会发现,亮面在另一面
平行光
- 平行光的光线是平行的,也就是说物体的每一个区域接收到的入射角是相同的
- 在设置的时候,使用
position
和target
两个属性来一起确定平行光的方向target
的属性值可以是threejs
场景中任何一个三维模型
// 平行光设置
var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 两点确定一条直线,我们要找两个点,一个是我们设置的点(position),一个是物体(target)
directionalLight.position.set(80, 100, 50);
directionalLight.target = mesh;
scene.add(directionalLight);
平行光如果不设置position和target属性,那么光线默认从上往下照射,也就可以认为是从(0,1,0)
和(0,0,0)
两个点确定的直线
聚光灯
- 聚光灯是一个会沿着特定方向逐渐发散的光源,在一个立体空间会构成一个圆锥体
- 通过属性
angle
可以设置聚光灯发散的角度,照射位置和平行光相同是由position
和target
两个属性实现的
// 聚光灯设置
var spotLight = new THREE.SpotLight(0xffffff);
// 两点确定一条直线,我们要找两个点,一个是我们设置的点(position),一个是物体(target)
spotLight.position.set(200, 200, 200);
spotLight.target = mesh;
// 设置发散的角度
spotLight.angle = Math.PI / 100
scene.add(spotLight);
光源辅助对象
光源辅助对象,就像AxesHelper一样可以可视化显示坐标,他可以大致显示光照的方向
辅助对象 | 构造函数名 |
---|---|
聚光源辅助对象 | SpotLightHelper |
点光源辅助对象 | PointLightHelper |
平行光光源辅助对象 | DirectionalLightHelper |
// 光源对象设置
const sphereSize = 2;
const pointLightHelper = new THREE.PointLightHelper( point, sphereSize,"#000" );
scene.add( pointLightHelper );
相关计算
颜色计算
- 当不同颜色的光源照射到有颜色的材质上面去的时候,当光源的颜色和网格模型材质的颜色值
mesh.material.color
和光源的颜色值light.color
会进行简单的相乘,也就是RGB三个分量分别进行相乘 - 平行光漫反射的数学模型:
漫反射光的颜色 = 网格模型材质颜色值 x 光线颜色 x 光线入射角余弦值
- 漫反射数学模型RGB分量表示:
(R2,G2,B2) = (R1,G1,B1) x (R0,G0,B0) x cosθ
R2 = R1 * R0 * cosθ
G2 = G1 * G0 * cosθ
B2 = B1 * B0 * cosθ
阴影
有方向的光源的作用下,物体都会形成隐形,想要产生阴影,需要有三个要素
- 首先要有光源
- 要有投影的模型
- 要有接收投影的模型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
body {
margin: 0;
overflow: hidden;
/* 隐藏body窗口区域滚动条 */
}
</style>
<!--引入three.js三维引擎-->
<script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
<!-- 引入threejs扩展控件OrbitControls.js -->
<script src="http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
<script>
/**
* 创建场景对象Scene
*/
var scene = new THREE.Scene();
/**
* 创建网格模型
*/
var geometry = new THREE.BoxGeometry(40, 100, 40); //创建一个立方体几何对象Geometry
var material = new THREE.MeshLambertMaterial({
color: 0x0000ff
}); //材质对象Material
var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
scene.add(mesh); //网格模型添加到场景中
// 设置产生投影的网格模型
mesh.castShadow = true;
// mesh.position.set(0,0,0)
//创建一个平面几何体作为投影面
var planeGeometry = new THREE.PlaneGeometry(300, 200);
var planeMaterial = new THREE.MeshLambertMaterial({
color: 0x999999
}); //材质对象Material
// 平面网格模型作为投影面
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial); //网格模型对象Mesh
scene.add(planeMesh); //网格模型添加到场景中
planeMesh.rotateX(-Math.PI / 2); //旋转网格模型
planeMesh.position.y = -50; //设置网格模型y坐标
// 设置接收阴影的投影面
planeMesh.receiveShadow = true;
/**
* 光源设置
*/
//环境光 环境光颜色RGB成分分别和物体材质颜色RGB成分分别相乘
var ambient = new THREE.AmbientLight(0x444444);
scene.add(ambient); //环境光对象添加到scene场景中
// 方向光
var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 设置光源位置
directionalLight.position.set(60, 100, 40);
scene.add(directionalLight);
// 设置用于计算阴影的光源对象
directionalLight.castShadow = true;
// 设置计算阴影的区域,最好刚好紧密包围在对象周围
// 计算阴影的区域过大:模糊 过小:看不到或显示不完整
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 300;
directionalLight.shadow.camera.left = -50;
directionalLight.shadow.camera.right = 50;
directionalLight.shadow.camera.top = 200;
directionalLight.shadow.camera.bottom = -100;
// 设置mapSize属性可以使阴影更清晰,不那么模糊
// directionalLight.shadow.mapSize.set(1024,1024)
console.log(directionalLight.shadow.camera);
/**
* 相机设置
*/
var width = window.innerWidth; //窗口宽度
var height = window.innerHeight; //窗口高度
var k = width / height; //窗口宽高比
var s = 150; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(200, 300, 200); //设置相机位置
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
/**
* 创建渲染器对象
*/
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height); //设置渲染区域尺寸
renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
// 设置渲染器,允许场景中使用阴影贴图
renderer.shadowMap.enabled = true;
// 渲染函数
function render() {
renderer.render(scene, camera); //执行渲染操作
}
render();
//创建控件对象 相机对象camera作为参数 控件可以监听鼠标的变化,改变相机对象的属性
var controls = new THREE.OrbitControls(camera, renderer.domElement);
//监听鼠标事件,触发渲染函数,更新canvas画布渲染效果
controls.addEventListener('change', render);
</script>
</body>
</html>
我们可以将上面的代码进行复制,渲染出来的效果如下
- 在这里,我们设置了投影面,并让投影面接收阴影
// 平面网格模型作为投影面
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial); //网格模型对象Mesh
scene.add(planeMesh); //网格模型添加到场景中
planeMesh.rotateX(-Math.PI / 2); //旋转网格模型
planeMesh.position.y = -50; //设置网格模型y坐标
// 设置接收阴影的投影面
planeMesh.receiveShadow = true;
- 然后设置了阴影的计算区域
// 设置用于计算阴影的光源对象
directionalLight.castShadow = true;
// 设置计算阴影的区域,最好刚好紧密包围在对象周围
// 计算阴影的区域过大:模糊 过小:看不到或显示不完整
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 300;
directionalLight.shadow.camera.left = -50;
directionalLight.shadow.camera.right = 50;
directionalLight.shadow.camera.top = 200;
directionalLight.shadow.camera.bottom = -100;
// 设置mapSize属性可以使阴影更清晰,不那么模糊
// directionalLight.shadow.mapSize.set(1024,1024)
相关属性
castShadow
- 模型和光源都有这个属性,且都是布尔值
- 如果是模型的
castShadow
,它主要用来设置模型对象在光源下是否产生阴影 - 如果是光源的
castShadow
,那么光源将会设置动态的阴影,这需要消耗很多动态资源,使投影看起正确
receiveShadow
- 他也是一个布尔值,用于设置一个模型对象是否在光照下接受其他模型的投影
shadow
- 光源的
shadow
属性是一个对象,不同光源的属性值,他们的光阴影对象也是不同的
种类 | 对象 | 阴影对象 |
---|---|---|
平行光 | DirectionalLight | DirectionalLightShadow |
聚光源 | SpotLight | SpotLightShadow |
LightShadow
LightShadow是所有阴影对象的基类,他有一个属性叫做camera
- 这个是观察光源的相机对象。这里可以看官网的解释 点击,他用于生成场景的深度图
基类
- 光源都有一个共同的基类,那就是Light
- 而Light也有一个基类叫做Object3D
- 在基类中,光源有两个常用的属性
- color:他的默认值是
0xffffff
- intensity:他的默认值是1.0
- 光照计算的时候会把两个属性值进行相乘
- color:他的默认值是