three各种光源类型知识

181 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

光源类型

设置光源对象是为了让场景中提高ThreeJS的渲染效果。因此,ThreeJS场景对象为Scene主要是由模型对象mesh光源对象light构成的。例如:scene.add(mesh)、scene.add(light)。光源对象有几种不同光源的类型,如下图:

微信截图_20221224181701.png

环境光(AmbientLight)

环境光一般是没有方向的,最多的是让物体对象明暗的现象。这环境光有两个参数,分别是颜色(color)和强度(intensity)。强度一般默认是1,数值越大灯光强度越亮。

// 环境光 
const color = OxFFFFFF; 
const intensity = 1; 
const light = new THREE.AmbientLight(color, intensity); 
// 让灯光添加到场景中 
scene.add(light);

效果图:

微信截图_20221224182812.png

平行光(DirectionalLight)

平行光一般像太阳光射线一样,但是和它们光源类型不同,就算有了光线方向,但是物体对象是起不作用的。因此这种平行光提供了位置.position和目标.target,同时一起可以确定平行光方向,例如这种目标.target就是一般针对在场景中任何一个三维模型对象光源的效果。

//平行光(DirectionalLight) 
const color = 0xFFFFFF; 
const intensity = 1; 
const light = new THREE.DirectionalLight(color, intensity); 
light.position.set(0, 10, 0); 
light.target.position.set(-5, 0, 0); 
scene.add(light); 
scene.add(light.target);

效果图:

微信截图_20221224185320.png 如果对于这种光源的位置及灯光的方向还是模糊,或者空间感不好的人,ThreeJS提供了有一堆辅助对象,可以让辅助对象到场景中,在场景中可以看出它们的方向及光源类型。

采用DirectionalLightHelper辅助对象加入到场景中,能可以实现看出它们的灯光。

//采用灯光光源 
const helper = new THREE.DirectionalLightHelper(light); 
scene.add(helper); 
//创建一个调用平行光和目标的位置函数 
function makeXYZGUI(gui, vector3, name, onChangeFn){ 
// gui组件的调用 
const folder = gui.addFolder(name); 
folder.add(vector3, 'x', -10, 10).onChange(onChangeFn);
folder.add(vector3, 'y', 0, 10).onChange(onChangeFn); 
folder.add(vector3, 'z', -10, 10).onChange(onChangeFn); 
folder.open(); 
} 

function updateLight(){ 
light.target.updateMatrixWorld(); 
helper.update(); 
} 
updateLight(); 
//GUI交互 
const gui = new GUI(); 
gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color'); 
gui.add(light, 'intensity', 0, 2, 0.01); 
//平行光的位置
makeXYZGUI(gui, light.position, 'position', updateLight); 
//平行光的目标 
makeXYZGUI(gui, light.target.position, 'target', updateLight);

gui组件就是提供工具的,然后调灯光辅助工具的位置,在模型中支持可以实时更新灯光辅助工具的位置。注意:如果我们更改gui方向的属性的时候,一般需要调用gui的函数, 然后可以更新,所以,需要传入一个onChangeFn函数以在GUI更新值时调用。

效果图:

微信截图_20221224190531.png

点光源(PointLight)

点光源一般是光线从发光核心向外发散。除了intensity和position,还附加属性有distance。如果distance为0,那么整个发光到无穷大。如果大于0的话,那么整个灯光强度照射在灯光上,而且远离灯光的位置,灯光强度就会减少。

// 点光源         
const color = 0xFFFFFF;         
const intensity = 1;        
const light = new THREE.PointLight(color, intensity);         
light.position.set(0100);         
scene.add(light);

效果图:

微信截图_20221224190708.png

聚光灯光源(SpootLight)

聚光灯一般是就会发散的光源,在场景中就像是圆锥体。除了position位置和target目标,还增加了angle、penumbra的属性。angle属性就是圆锥体的锥角大小,这个值越大,那么圆锥体的锥角就会变大;penumbra属性就是比如锥体的中心灯光强度减少到外锥体。

//聚光灯 
const color = 0xFFFFFF;    
const intensity = 1;   
const light = new THREE.SpotLight(color, intensity);   
light.position.set(0100);    
light.target.position.set(-500);   
scene.add(light);   
scene.add(light.target);

效果图:

微信截图_20221224190937.png

光源辅助对象

辅助对象构造函数名
聚光源辅助对象SpotLightHelper
点光源辅助对象PointLightHelper
平行光光源辅助对象DirectionalLightHelper

思考问题:

如果创建多个灯光,还有创建一个灯光对象,另一个创建不同的灯光对象,如何解决?这种基本可以解决,不建议创建过多个光源对象,至少两个不同的灯光对象即可。

// 聚光灯 
const color = 0xFFFFFF; const intensity = 1; 
const light = new THREE.SpotLight(color, intensity); 
scene.add(light); scene.add(light.target);          
// 点光源 
const light1 = new THREE.PointLight(color, intensity); 
light1.position.set(15100); 
scene.add(light1); 
// 聚光灯辅助对象 
const helper = new THREE.SpotLightHelper(light); 
scene.add(helper);
// 点光源辅助对象 
const helper1 = new THREE.PointLightHelper(light1); 
scene.add(helper1);

效果图:

微信截图_20221224191535.png

注意:在任何场景中,如果添加过多的灯光都会使渲染场景速度越慢,一般是添加至少一二个灯光即可。