【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

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MAXLZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值