【Three.js】四(2)、three.js中的光源——特殊光源
一、THREE.HemisphereLight
创建更加贴近自然的户外光照效果。
1.1 构造器
/**
* skyColor: 从天空发出颜色
* groundColor:从地面发出的颜色
* intensity:光线照射强度
*/
HemisphereLight( skyColor : Integer, groundColor : Integer, intensity : Float )
1.2 属性说明
属性 | 说明 |
---|---|
color | 从天空发出的颜色 |
groundColor | 从地面发出的颜色 |
intensity | 光照强度 |
visible | 是否可见 |
示例:
import '../../stylus/index.styl';
import image from '../../assets/images/grasslight-big.jpg'
import * as THREE from 'three';
import * as dat from 'dat.gui';
import {initStats,initTrackballControls} 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, 10000);
camera.position.set(-30,30,30);
let renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
let textureGrass = new THREE.TextureLoader().load(image);
textureGrass.wrapS = THREE.RepeatWrapping;
textureGrass.wrapT = THREE.RepeatWrapping;
textureGrass.repeat.set(10, 10);
let planeGeometry = new THREE.PlaneBufferGeometry(500, 500,20,20);
let planeMaterial = new THREE.MeshLambertMaterial({
map: textureGrass
});
let plane = new THREE.Mesh(planeGeometry,planeMaterial);
plane.receiveShadow = true;
plane.rotation.x = -0.5 * Math.PI;
plane.position.set(0,0,0);
scene.add(plane);
let spotLight = new THREE.SpotLight(0xcccccc);
spotLight.position.set(-40, 60, -10);
scene.add(spotLight);
let hemisphereLight = new THREE.HemisphereLight(0x0000ff, 0x00ff00, 0.6);
hemisphereLight.castShadow = true;
hemisphereLight.position.set( 0, 500, 0 );
scene.add(hemisphereLight);
let dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(30, 10, -50);
dirLight.castShadow = true;
dirLight.target = plane;
dirLight.shadow.camera.near = 0.1;
dirLight.shadow.camera.far = 200;
dirLight.shadow.camera.left = -50;
dirLight.shadow.camera.right = 50;
dirLight.shadow.camera.top = 50;
dirLight.shadow.camera.bottom = -50;
dirLight.shadow.mapSize.set(2048, 2048);
scene.add(dirLight);
let ambientLight = new THREE.AmbientLight(0xc2c2c2);
scene.add(ambientLight);
let cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
let cubeMaterial = new THREE.MeshLambertMaterial({
color: 0xff3333
});
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
cube.position.set(-4,3,0);
scene.add(cube);
let sphereGeometry = new THREE.SphereGeometry(4, 25, 25);
let sphereMaterial = new THREE.MeshPhongMaterial({
color: 0x7777ff
});
let sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(10,5,10);
sphere.castShadow = true;
scene.add(sphere);
let gui = new dat.GUI();
let controls = {
visible: hemisphereLight.visible,
skyColor: hemisphereLight.color.getStyle(),
groundColor: hemisphereLight.groundColor.getStyle(),
intensity: hemisphereLight.intensity
};
gui.add(controls, 'visible');
gui.addColor(controls, 'skyColor');
gui.addColor(controls, 'groundColor');
gui.add(controls, 'intensity', 0, 2);
let trackballControl = initTrackballControls(camera, renderer);
function render(){
stats.update();
trackballControl.update();
hemisphereLight.visible = controls.visible;
hemisphereLight.color = new THREE.Color(controls.skyColor);
hemisphereLight.groundColor = new THREE.Color(controls.groundColor);
hemisphereLight.intensity = controls.intensity;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
}
init();
完整示例(src/three_HemisphereLight_demo):https://github.com/MAXLZ1/threejs_demo
二、THREE.RectAreaLight
在一个矩形平面上均匀地发出光线。这种光可用于模拟光源,如明亮的窗户或条状照明。
注意:
- 该光源无阴影支持。
- 只支持MeshStandardMaterial和MeshPhysicalMaterial
- 必须在场景中包含RectAreaLightUniformsLib并调用init()
import '../../stylus/index.styl'
import * as THREE from 'three';
import * as dat from 'dat.gui';
import Stats from 'stats-js';
import {initTrackballControls, initStats} from "../../util/util";
import {RectAreaLightUniformsLib} from '../../libs/RectAreaLightUniformsLib'
const OrbitControls = require('three-orbitcontrols')
var renderer, scene, camera;
var origin = new THREE.Vector3();
var rectLight;
var param = {};
var stats;
init();
animate();
function init() {
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;
renderer.gammaInput = true;
renderer.gammaOutput = true;
document.body.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 20, 35 );
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0xffffff, 0.1 );
scene.add( ambient );
RectAreaLightUniformsLib.init();
rectLight = new THREE.RectAreaLight( 0xffffff, 1, 10, 10 );
rectLight.position.set( 5, 0, 0 );
scene.add( rectLight );
var rectLightMesh = new THREE.Mesh( new THREE.PlaneBufferGeometry(), new THREE.MeshBasicMaterial( { side: THREE.BackSide } ) );
rectLightMesh.scale.x = rectLight.width;
rectLightMesh.scale.y = rectLight.height;
rectLight.add( rectLightMesh );
var rectLightMeshBack = new THREE.Mesh( new THREE.PlaneBufferGeometry(), new THREE.MeshBasicMaterial( { color: 0x080808 } ) );
rectLightMesh.add( rectLightMeshBack );
var geoFloor = new THREE.BoxBufferGeometry( 2000, 0.1, 2000 );
var matStdFloor = new THREE.MeshStandardMaterial( { color: 0x808080, roughness: 0, metalness: 0 } );
var mshStdFloor = new THREE.Mesh( geoFloor, matStdFloor );
mshStdFloor.position.set(0,0,0);
scene.add( mshStdFloor );
var matStdObjects = new THREE.MeshStandardMaterial( { color: 0xA00000, roughness: 0, metalness: 0 } );
var geoBox = new THREE.BoxBufferGeometry( Math.PI, Math.sqrt( 2 ), Math.E );
var mshStdBox = new THREE.Mesh( geoBox, matStdObjects );
mshStdBox.position.set( 0, 5, 0 );
mshStdBox.rotation.set( 0, Math.PI / 2.0, 0 );
mshStdBox.castShadow = true;
mshStdBox.receiveShadow = true;
scene.add( mshStdBox );
var geoSphere = new THREE.SphereBufferGeometry( 1.5, 32, 32 );
var mshStdSphere = new THREE.Mesh( geoSphere, matStdObjects );
mshStdSphere.position.set( - 5, 5, 0 );
mshStdSphere.castShadow = true;
mshStdSphere.receiveShadow = true;
scene.add( mshStdSphere );
var geoKnot = new THREE.TorusKnotBufferGeometry( 1.5, 0.5, 100, 16 );
var mshStdKnot = new THREE.Mesh( geoKnot, matStdObjects );
mshStdKnot.position.set( 5, 5, 0 );
mshStdKnot.castShadow = true;
mshStdKnot.receiveShadow = true;
scene.add( mshStdKnot );
var controls = new OrbitControls( camera, renderer.domElement );
controls.target.copy( mshStdBox.position );
controls.update();
// GUI
var gui = new dat.GUI( { width: 300 } );
gui.open();
param = {
motion: true,
width: rectLight.width,
height: rectLight.height,
color: rectLight.color.getHex(),
intensity: rectLight.intensity,
'ambient': ambient.intensity,
'floor color': matStdFloor.color.getHex(),
'object color': matStdObjects.color.getHex(),
'roughness': matStdFloor.roughness,
'metalness': matStdFloor.metalness
};
gui.add( param, 'motion' );
var lightFolder = gui.addFolder( 'Light' );
lightFolder.add( param, 'width', 1, 20 ).step( 0.1 ).onChange( function ( val ) {
rectLight.width = val;
rectLightMesh.scale.x = val;
} );
lightFolder.add( param, 'height', 1, 20 ).step( 0.1 ).onChange( function ( val ) {
rectLight.height = val;
rectLightMesh.scale.y = val;
} );
lightFolder.addColor( param, 'color' ).onChange( function ( val ) {
rectLight.color.setHex( val );
rectLightMesh.material.color.copy( rectLight.color ).multiplyScalar( rectLight.intensity );
} );
lightFolder.add( param, 'intensity', 0.0, 4.0 ).step( 0.01 ).onChange( function ( val ) {
rectLight.intensity = val;
rectLightMesh.material.color.copy( rectLight.color ).multiplyScalar( rectLight.intensity );
} );
lightFolder.add( param, 'ambient', 0.0, 0.2 ).step( 0.01 ).onChange( function ( val ) {
ambient.intensity = val;
} );
lightFolder.open();
var standardFolder = gui.addFolder( 'Standard Material' );
standardFolder.addColor( param, 'floor color' ).onChange( function ( val ) {
matStdFloor.color.setHex( val );
} );
standardFolder.addColor( param, 'object color' ).onChange( function ( val ) {
matStdObjects.color.setHex( val );
} );
standardFolder.add( param, 'roughness', 0.0, 1.0 ).step( 0.01 ).onChange( function ( val ) {
matStdObjects.roughness = val;
matStdFloor.roughness = val;
} );
standardFolder.add( param, 'metalness', 0.0, 1.0 ).step( 0.01 ).onChange( function ( val ) {
matStdObjects.metalness = val;
matStdFloor.metalness = val;
} );
standardFolder.open();
stats = new Stats();
document.body.appendChild( stats.dom );
}
function animate() {
requestAnimationFrame( animate );
if ( param.motion ) {
var t = ( Date.now() / 2000 );
var r = 15.0;
var lx = r * Math.cos( t );
var lz = r * Math.sin( t );
var ly = 5.0 + 5.0 * Math.sin( t / 3.0 );
rectLight.position.set( lx, ly, lz );
rectLight.lookAt( origin );
}
renderer.render( scene, camera );
stats.update();
}
三、THREE.LensFlare
光晕。
创建一个简单光晕:
let textureLoader = new THREE.TextureLoader();
let textureFlare1 = textureLoader.load( image1 );
let textureFlare2 = textureLoader.load( image2 );
let pointLight = new THREE.PointLight( 0xff0000, 1.5, 2000 );
pointLight.position.set( 15, 15, 0 );
scene.add( pointLight );
let lensflare = new Lensflare();
// 光晕
lensflare.addElement( new LensflareElement( textureFlare1, 100, 0, pointLight.color ) );
// 光斑
lensflare.addElement( new LensflareElement( textureFlare2, 60, 0.6 ) );
lensflare.addElement( new LensflareElement( textureFlare2, 70, 0.7 ) );
lensflare.addElement( new LensflareElement( textureFlare2, 120, 0.9 ) );
lensflare.addElement( new LensflareElement( textureFlare2, 70, 1 ) );
pointLight.add( lensflare );
3.1 构造器
/**
* texture:纹理
* size: 大小
* distance: 距离
* color: 光晕颜色
*/
LensflareElement( texture : Texture, size : Float, distance : Float, color : Color )
示例:
import '../../stylus/index.styl'
import * as THREE from 'three';
import image1 from '../../assets/images/lensflare0.png';
import image2 from '../../assets/images/lensflare3.png';
import {Lensflare,LensflareElement} from "../../libs/Lensflare";
import * as dat from 'dat.gui';
import {initStats,initTrackballControls} from "../../util/util";
function init(){
let states = initStats();
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
camera.position.set(-40,30,30);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
scene.add(camera);
let planeGeometry = new THREE.PlaneGeometry(100,100,1,1);
let planeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
});
let plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = - 0.5 * Math.PI;
plane.position.set(0,0,0);
plane.receiveShadow = true;
scene.add(plane);
let spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(30, 30, 0);
spotLight.shadow.mapSize.set(2048, 2048);
spotLight.castShadow = true;
scene.add(spotLight);
let ambienLight = new THREE.AmbientLight(0xc2c2c2, 0.2);
scene.add(ambienLight);
// 光晕
let textureLoader = new THREE.TextureLoader();
let textureFlare1 = textureLoader.load( image1 );
let textureFlare2 = textureLoader.load( image2 );
let pointLight = new THREE.PointLight( 0xff0000, 1.5, 2000 );
pointLight.position.set( 15, 15, 0 );
scene.add( pointLight );
let lensflare = new Lensflare();
lensflare.addElement( new LensflareElement( textureFlare1, 100, 0, pointLight.color ) );
lensflare.addElement( new LensflareElement( textureFlare2, 60, 0.6 ) );
lensflare.addElement( new LensflareElement( textureFlare2, 70, 0.7 ) );
lensflare.addElement( new LensflareElement( textureFlare2, 120, 0.9 ) );
lensflare.addElement( new LensflareElement( textureFlare2, 70, 1 ) );
pointLight.add( lensflare );
let cubeGeometry = new THREE.BoxGeometry(4,4,4);
let cubeMaterial = new THREE.MeshLambertMaterial({
color: 0xff0000
});
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.set(2,4, 2);
cube.castShadow = true;
scene.add(cube);
camera.lookAt(scene.position);
let trackballControls = initTrackballControls(camera, renderer);
function render() {
states.update();
trackballControls.update();
requestAnimationFrame(render);
renderer.render(scene,camera);
}
render();
}
init();
完整示例(src/three_LensFlare_demo):https://github.com/MAXLZ1/threejs_demo