【Three.js】四(1)、three.js中的光源——基础光源
three.js中的光源有:THREE.AmbientLight、THREE.PointLight、THREE.SpotLight、THREE.DirectionLight、THREE.HemisphereLight、THREE.AreaLight、THREE.LensFlare,下面我们一一介绍这些光源的区别。
一、THREE.AmbientLight
环境光。这是一个基本光源,该光源的颜色将会叠加到场景现有物体的颜色上。
THREE.AmbientLight创建的光源,颜色会被应用至全局。该光源没有特定来源方向,并且不会产生阴影。通常不会单独使用它,而是配合其他光源同时使用,目的是弱化阴影或给场景添加一些额外的颜色。
创建环境光非常简单,只需new THREE.AmbientLight()
,然后将其添加到场景中即可,无需设置光照位置。下面是一个可通过dat.GUI控制环境光的示例:
import '../../stylus/index.styl'
import * as THREE from 'three'
import * as dat from 'dat.gui'
import {initStats} from '../../util/util'
function init() {
let stats = initStats();
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 100);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
scene.add(camera);
let planeGeomerty = new THREE.PlaneGeometry(60,40,1, 1);
let planeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
});
let plane = new THREE.Mesh(planeGeomerty, planeMaterial);
plane.rotation.x = -0.5 * Math.PI;
plane.receiveShadow = true;
scene.add(plane);
let spotLight = new THREE.SpotLight(0xffffff, 1,180, Math.PI / 4);
spotLight.castShadow = true;
spotLight.position.set(-30, 40, -10);
spotLight.shadow.mapSize.set(2048, 2048);
scene.add(spotLight);
let ambientLight = new THREE.AmbientLight(0x606008, 1);
scene.add(ambientLight);
let gui = new dat.GUI();
let controls = new function(){
this.intensity = ambientLight.intensity;
this.ambientColor = ambientLight.color.getStyle();
};
gui.add(controls, 'intensity', 0, 1).onChange(value => {
ambientLight.color = new THREE.Color(controls.ambientColor);
ambientLight.intensity = controls.intensity;
});
gui.addColor(controls, 'ambientColor').onChange(value => {
ambientLight.color = new THREE.Color(controls.ambientColor);
ambientLight.intensity = controls.intensity;
});
let cubeGeometry = new THREE.BoxGeometry(4,4,4);
let cubeMaterial = new THREE.MeshLambertMaterial({
color: 0x00ffff
});
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
cube.position.x = 2;
cube.position.y = 2;
cube.position.z = 2;
scene.add(cube);
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 40;
camera.lookAt(scene.position);
document.body.appendChild(renderer.domElement);
render();
function render(){
stats.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
}
window.onload = init();
完整示例(src/three_demo_05):https://github.com/MAXLZ1/threejs_demo
二、THREE.PointLight
点光源。一种单点发光、照射所有方向的光源。例如蜡烛。
要创建一个点光源非常简单:
let pointLight = new THREE.PointLight(0xffffff);
pointLight.castShadow = true;
pointLight.shadow.mapSize.set(2048, 2048);
pointLight.decay = 0.1
scene.add(pointLight);
我们使用指定颜色创建了一个点光源,并使其可产生阴影,通过mapSize设置了阴影的清晰度,decay设置沿着光照距离的衰退量。
下
2.1 THREE.PointLight属性
属性 | 说明 |
---|---|
color | 光源颜色 |
distance | 光源照射距离。默认为0,光的强度不会随着距离增加而减少 |
intensity | 光源照射的强度。默认为1 |
position | 光源在场景中的位置 |
visible | 是否开启光源 |
面示例展示了这几个属性的使用:
function init() {
let stats = initStats();
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 100);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
scene.add(camera);
let planeGeomerty = new THREE.PlaneGeometry(60,40,1, 1);
let planeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
});
let plane = new THREE.Mesh(planeGeomerty, planeMaterial);
plane.rotation.x = -0.5 * Math.PI;
plane.receiveShadow = true;
scene.add(plane);
let pointLight = new THREE.PointLight(0xffffff);
pointLight.castShadow = true;
pointLight.shadow.mapSize.set(2048, 2048);
pointLight.decay = 0.1
scene.add(pointLight);
// 光源辅助线
let helper = new THREE.PointLightHelper(pointLight);
scene.add(helper);
// 阴影辅助线
let shadowHelper = new THREE.CameraHelper(pointLight.shadow.camera)
scene.add(shadowHelper)
let ambientLight = new THREE.AmbientLight(0x353535, 1);
scene.add(ambientLight);
// 创建球模拟光源
let sphereLight = new THREE.SphereGeometry(0.2);
let sphereLightMaterial = new THREE.MeshBasicMaterial({
color: 0xac6c25
});
let sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);
sphereLightMesh.position.set(0, 8, 2);
scene.add(sphereLightMesh);
let gui = new dat.GUI();
let controls = new function(){
this.intensity = pointLight.intensity;
this.pointColor = pointLight.color.getStyle();
this.distance = pointLight.distance;
this.visible = pointLight.visible;
};
gui.add(controls, 'intensity', 0, 2).onChange(value => {
pointLight.color = new THREE.Color(controls.pointColor);
pointLight.intensity = controls.intensity;
});
gui.addColor(controls, 'pointColor').onChange(value => {
pointLight.color = new THREE.Color(controls.pointColor);
pointLight.intensity = controls.intensity;
});
gui.add(controls, 'distance', 0, 100);
gui.add(controls, 'visible');
let cubeGeometry = new THREE.BoxGeometry(4,4,4);
let cubeMaterial = new THREE.MeshLambertMaterial({
color: 0x00ffff
});
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
cube.position.x = 2;
cube.position.y = 2;
cube.position.z = 2;
scene.add(cube);
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 40;
camera.lookAt(scene.position);
document.body.appendChild(renderer.domElement);
let trackballControls = initTrackballControls(camera, renderer);
let step = 0;
function render(){
helper.update();
shadowHelper.update();
stats.update();
trackballControls.update();
step += 0.01;
sphereLightMesh.position.x = 20 + (10 * Math.cos(step));
sphereLightMesh.position.y = 2 + (10* Math.abs(Math.sin(step)));
sphereLightMesh.translateX(-18);
// 球的位置赋给光源
pointLight.position.copy(sphereLightMesh.position);
pointLight.distance = controls.distance;
pointLight.visible = controls.visible;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
}
window.onload = init();
完整示例(src/three_demo_06):https://github.com/MAXLZ1/threejs_demo
三、THREE.SpotLight
聚光灯光源,最常用的光源。锥形效果的光源,例如手电筒。
简单创建一个光源:
let spotLight = new THREE.SpotLight(0xffffff, 1,180, Math.PI / 4);
spotLight.castShadow = true;
spotLight.position.set(-30, 40, -10);
spotLight.shadow.mapSize.set(2048, 2048);
scene.add(spotLight);
3.1 THREE.SpotLight属性
属性 | 说明 |
---|---|
angle | 光源发射出光束的宽度,单位是弧度,默认Math.PI/2 |
castShdow | 设置是否产生阴影 |
color | 光源颜色 |
distance | 光源照射的距离,默认为0,光线强度不会随着距离增加而减弱 |
decay | 光沿着光的距离变暗的量,在标准物理状态下,该值为2代表真实的光衰减,默认为1 |
isSpotLight | 是否我聚光灯光源,最好不要更改该值 |
penumbra | |
intensity | 光源照射强度。默认1 |
position | 光源在场景中的位置。 |
target | 将光源指向场景中的特定对象或位置 |
visible | 光源是否开启 |
下方是来自官网示例:
import '../../stylus/index.styl'
import * as THREE from 'three'
import * as dat from 'dat.gui'
import {initStats,initTrackballControls} from '../../util/util'
const OrbitControls = require('three-orbitcontrols')
var renderer, scene, camera;
var spotLight, lightHelper, shadowCameraHelper;
var gui;
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.gammaInput = true;
renderer.gammaOutput = true;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 65, 8, - 10 );
var controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.minDistance = 20;
controls.maxDistance = 500;
controls.enablePan = false;
var ambient = new THREE.AmbientLight( 0xffffff, 0.1 );
scene.add( ambient );
spotLight = new THREE.SpotLight( 0xffffff, 1 );
spotLight.position.set( 15, 40, 35 );
spotLight.angle = Math.PI / 4;
spotLight.penumbra = 0.05;
spotLight.decay = 2;
spotLight.distance = 200;
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 10;
spotLight.shadow.camera.far = 200;
spotLight.visible = true;
scene.add( spotLight );
lightHelper = new THREE.SpotLightHelper( spotLight );
scene.add( lightHelper );
shadowCameraHelper = new THREE.CameraHelper( spotLight.shadow.camera );
scene.add( shadowCameraHelper );
scene.add( new THREE.AxesHelper( 10 ) );
var material = new THREE.MeshPhongMaterial( { color: 0x808080, dithering: true } );
var geometry = new THREE.PlaneBufferGeometry( 2000, 2000 );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 0, - 1, 0 );
mesh.rotation.x = - Math.PI * 0.5;
mesh.receiveShadow = true;
scene.add( mesh );
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 );
mesh.castShadow = true;
scene.add( mesh );
controls.target.copy( mesh.position );
controls.update();
window.addEventListener( 'resize', onResize, false );
}
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function render() {
lightHelper.update();
shadowCameraHelper.update();
renderer.render( scene, camera );
}
function buildGui() {
gui = new dat.GUI();
var params = {
'light color': spotLight.color.getHex(),
intensity: spotLight.intensity,
distance: spotLight.distance,
angle: spotLight.angle,
penumbra: spotLight.penumbra,
decay: spotLight.decay,
visible: spotLight.visible
};
gui.addColor( params, 'light color' ).onChange( function ( val ) {
spotLight.color.setHex( val );
render();
} );
gui.add( params, 'intensity', 0, 2 ).onChange( function ( val ) {
spotLight.intensity = val;
render();
} );
gui.add( params, 'distance', 50, 200 ).onChange( function ( val ) {
spotLight.distance = val;
render();
} );
gui.add( params, 'angle', 0, Math.PI / 3 ).onChange( function ( val ) {
spotLight.angle = val;
render();
} );
gui.add( params, 'penumbra', 0, 1 ).onChange( function ( val ) {
spotLight.penumbra = val;
render();
} );
gui.add( params, 'decay', 1, 2 ).onChange( function ( val ) {
spotLight.decay = val;
render();
} );
gui.add(params, 'visible').onChange(val => {
spotLight.visible = val;
render();
})
gui.open();
}
init();
buildGui();
render();
完整示例(src/three_demo_07):https://github.com/MAXLZ1/threejs_demo
四、THREE.DirectionalLight
平行光源,常用来模拟太阳光。由特点方向发出的光,产生的光线都是平行的,太阳光可近似看为平行光。
4.1THREE.DirectionalLight的属性
属性 | 说明 |
---|---|
color | 光照颜色 |
castShadow | 是否产生阴影 |
position | 位置 |
target | 将光源指向场景中的特定对象或位置 |
示例:
import '../../stylus/index.styl';
import {initStats} from "../../util/util";
const OrbitControls = require('three-orbitcontrols')
import * as THREE from 'three';
import * as dat from 'dat.gui';
function init(){
let stats = initStats();
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1, 1000);
camera.position.set(65, 8,-10);
let renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
scene.add(camera);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
let control = new OrbitControls( camera, renderer.domElement );
control.addEventListener( 'change', render );
control.minDistance = 30;
control.maxDistance = 500;
control.enablePan = false;
let planeGeometry = new THREE.PlaneBufferGeometry(2000,2000);
let planeMaterial = new THREE.MeshLambertMaterial({color: 0x808080});
let plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = - Math.PI * 0.5;
plane.position.set(0,0,0);
plane.receiveShadow = true;
scene.add(plane);
let cubeGeometry = new THREE.BoxGeometry(4,4,4);
let cubeMaterial = new THREE.MeshPhongMaterial({color:0x3896fe});
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.set(0,10,0);
cube.castShadow = true;
scene.add(cube);
let ambientLight = new THREE.AmbientLight(0xc2c2c2);
scene.add(ambientLight);
let directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.set(2048, 2048);
directionalLight.position.set(0,20,-10);
directionalLight.shadow.camera.near = 10;
directionalLight.shadow.camera.far = 30;
directionalLight.shadow.camera.left = -10;
directionalLight.shadow.camera.right = 10;
directionalLight.shadow.camera.top = 10;
directionalLight.shadow.camera.bottom = -10;
directionalLight.target = cube;
scene.add(directionalLight);
let helper = new THREE.DirectionalLightHelper(directionalLight);
scene.add(helper);
let lightShadow = new THREE.CameraHelper(directionalLight.shadow.camera);
scene.add(lightShadow);
let controls = {
lightColor: directionalLight.color.getHex(),
castShadow: directionalLight.castShadow,
x: directionalLight.position.x,
y: directionalLight.position.y,
z: directionalLight.position.z
};
let gui = new dat.GUI();
gui.addColor(controls, 'lightColor');
gui.add(controls, 'castShadow');
let positionGUI = gui.addFolder('position');
positionGUI.add(controls, 'x', -20, 20);
positionGUI.add(controls, 'y', 0, 20);
positionGUI.add(controls, 'z', -20, 20);
function render(){
stats.update();
helper.update();
lightShadow.update();
directionalLight.color.setHex(controls.lightColor);
directionalLight.castShadow = controls.castShadow;
directionalLight.position.set(controls.x, controls.y, controls.z);
requestAnimationFrame(render);
renderer.render(scene, camera);
}
control.target.copy(cube.position);
control.update();
render();
}
init();
完整示例(src/three_DirectionalLight_demo):https://github.com/MAXLZ1/threejs_demo