three.js常见灯光及阴影的使用

three.js常见灯光的使用

环境光(AmbientLight) 点光源(PointLight) 聚光灯(SpotLight) 平行光(DirectinalLight)

<!DOCTYPE html>
<html lang="en">
<head>
    <title>threeJS常见灯光</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, 
    user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <!--引入three.js三维引擎-->
    <script src="three.js"></script>
    <script src="OrbitControls.js"></script>
    <link rel="stylesheet" href="main.css">
</head>
<body>
<script>
    // 场景, 相机, 渲染器
    var scene, camera, renderer;

    var pointLight, // 点光源,
        spotLight,  // 聚光灯, 
        lightHelper, // 模拟聚光灯,
        directionLight, // 平行光,
        shadowCameraHelper; // 模拟相机视锥体

    function init() {
        /**
         * 创建场景
         */
        scene = new THREE.Scene();

        /**
         * 创建透视相机对象
         */
        camera = new THREE.PerspectiveCamera( 
            35, // fov — 摄像机视锥体垂直视野角度
            window.innerWidth / window.innerHeight, // 长宽比
            1, // 摄像机视锥体近端面
            1000 // 摄像机视锥体远端面
        );
        // 设置相机位置
        camera.position.set( 65, 8, - 10 );

        /**
         * 创建渲染器
         */
        renderer = new THREE.WebGLRenderer();
        // 设置分辨率为当前设备的分辨率,解决场景模糊,抗锯齿的一-种很好的方法
        renderer.setPixelRatio( window.devicePixelRatio );
        // 设置渲染区域尺寸 宽高
        renderer.setSize( window.innerWidth, window.innerHeight );
        // 在body元素中插入canvas对象
        document.body.appendChild( renderer.domElement );
        // 告诉render我们需要阴影(允许阴影隐射) 
        renderer.shadowMap.enabled = true;
        // 使用PCF算法来过滤阴影映射
//https://threejs.org/docs/index.html?q=WebGLRenderer#api/zh/constants/Renderer
        renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        // 默认为 false. 如果设置了该参数,表示所有纹理和颜色应当使用预乘的gamma值来输入
        renderer.gammaInput = true;
        // 默认为 false. 如果设置了该参数,表示所有纹理和颜色应当使用预乘的gamma值来输出。
        renderer.gammaOutput = true;

        /**
         * 创建轨道控制器,实现用鼠标交互 旋转、平移,缩放
         * 关于OrbitControls轨道控制器的使用说明
         * http://www.yanhuangxueyuan.com/doc/Three.js/OrbitControls.html
         */
        var controls = new THREE.OrbitControls( camera, renderer.domElement );
        // 当鼠标移动时调用render方法 
        controls.addEventListener( 'change', render );
        // 视角最小距离
        controls.minDistance = 1;
        // 视角最远距离
        controls.maxDistance = 500;
        // 禁止右键拖拽
        controls.enablePan = false;

        /**
         * * 环境光
         * 笼罩在整个空间无处不在的光,环境光可以说是场景的整体基调,由于环境光无处不在,
         * 也就是说环境光是没有方向的,不能产生阴影。
         * 也不能作为环境中唯一的光源。否则后果就是所有的物体都是黑的
         * 具体作用就是弱化阴影或者给场景添加一些颜色,所以设置的时候只需要设置一些颜色即可
         */
        var ambient = new THREE.AmbientLight(
            0xffffff, // 颜色的rgb数值,不填默认0xffffff
            0.1 // 光照的强度。缺省值为 1
        );
        // 将环境光添加到场景中
        scene.add( ambient );

        /**
         * * 点光源
         * 点光源即向四面八方发射的单点光源,可以将点光源想象成萤火虫一样发出的光。
         * 由于它白的光线也发射到四面八方, 不能产生阴影
         * 原因是这样的光源会朝着所有的方向发射光线,
         * 在这种情况下计算阴影对GPU来讲是一个非常沉重的负担,所以不能产生阴影
         * 如果需要阴影可以使用 比如聚光灯SpotLight
         */
        pointLight = new THREE.PointLight(
            0xffffff, // 光照颜色,默认 0xffffff
            1 // 光照强度, 光照强度 默认 1
        );
        // 设置光源位置
        pointLight.position.set( 15, 40, 35 );
        // 从光源到光照强度为0的位置。当设置为0时,光永远不会消失(距离无穷大)
        pointLight.distance = 200;
        // 是否开启点光源
        pointLight.visible=true;
        // 将点光源添加到场景中
        scene.add( pointLight );

        /**
         * 聚光灯
         * 锥形效果的光源, 能够产生阴影
         */
        spotLight = new THREE.SpotLight( 0xffffff, 1 );
        // 设置聚光灯的位置
        spotLight.position.set( 15, 40, 35 );
        // 光线散射角度, 最大为Math.PI/2
        spotLight.angle = Math.PI / 4;
        // 聚光锥的半影衰减百分比。在0和1之间的值。 默认值 — 0.0。
        spotLight.penumbra = 0.05; //半影
        // 沿着光照距离的衰减量 设置为等于2将实现现实世界的光衰减 默认1
        spotLight.decay = 2; //衰落
        // 如果非零,那么光强度将会从最大值当前灯光位置处按照距离线性衰减到0. 默认为0.0
        spotLight.distance = 200;
        // 此属性设置为 true 聚光灯将投射阴影。
        // 警告: 这样做的代价比较高而且需要一直调整到阴影看起来正确。
        // 不是所有的光源都可以投射阴影,这里使用聚点光源可以产生阴影
        spotLight.castShadow = true;
        // 将聚光灯添加到场景中
        scene.add( spotLight );

        /**
         * 平行光
         * 平行光,类似太阳光,距离很远的光,如太阳般,照射到地球上每一束光都是平行行的。
         * 所有对象接收的光强都是一样的,会产生阴影,与聚点光源的主要差别是:
         * 聚点光源光距离目标越远光越暗淡,而平行光光强都是一样样的。
         * 用direction(方向),color(颜色),intensity(强度)来计算属性和阴影,
         * 形成的不是光锥而是一个方块,很重要
         */
        directionLight=new THREE.DirectionalLight(
            0xffffff, // 光的颜色 默认0xffffff
            1 // 光照的强度 默认1
        );
        // 平行光的位置
        directionLight.position.set( 15, 40, 35 );
        // 如果设置为 true 该平行光会产生动态阴影。
        directionLight.castShadow = true;
        // 如果非零,那么光强度将会从最大值当前灯光位置处按照距离线性衰减到0。 缺省值为 0.0
        directionLight.distance = 200;
        // 将平行光添加到场景中
        scene.add( directionLight );

        // 用于模拟聚光灯 SpotLight 的锥形辅助对象.
        lightHelper = new THREE.SpotLightHelper( spotLight );
        // 将模拟聚光灯辅助对象添加到场景中
        scene.add( lightHelper );

        // 用于模拟相机视锥体的辅助对象. 用来模拟相机视锥体
        shadowCameraHelper = new THREE.CameraHelper( spotLight.shadow.camera );
        // 将相机视锥体的辅助对象添加到场景中
        scene.add( shadowCameraHelper );

        // 用于简单模拟3个坐标轴的对象. 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
        scene.add( new THREE.AxesHelper( 10 ) );

        // 创建具有镜面高光的光泽表面的材质 
        // 颜色 0xffffff dithering 是否对颜色应用抖动以消除条带的外观
        var material = new THREE.MeshPhongMaterial( { 
            color: 0x808080, 
            dithering: true 
        } );
        // 创建一个缓冲平面 长宽
        var geometry = new THREE.PlaneBufferGeometry( 300, 300 );
        // 创建网格对象 物体 材质
        var mesh = new THREE.Mesh( geometry, material );
        // 设置网格对象的位置
        mesh.position.set( 0, - 1, 0 );
        // 沿着X轴旋转
        mesh.rotation.x = - Math.PI * 0.5;
        // 接受阴影
        mesh.receiveShadow = true; 
        // 将网格对象添加到场景中
        scene.add( mesh );
        
        // 创建具有镜面高光的光泽表面的材质 颜色 0xffffff 
        // dithering 是否对颜色应用抖动以消除条带的外观
        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 );
        // cast投射,就是允许方块投射阴影
        mesh.castShadow = true; 
        // 将网格对象添加到场景中
        scene.add( mesh );

        // 平行光的方向是从它的位置到目标位置。默认的目标位置为原点 (0,0,0)
        directionLight.target = mesh;

        // 轨道控制器的方向拷贝mesh的位置
        controls.target.copy( mesh.position );
        // 更新控制器。必须在摄像机的变换发生任何手动改变后调用
        controls.update();
        // 当浏览器发生改变时
        window.addEventListener( 'resize', onResize, false );
    }

    function onResize() {
        // 摄像机视锥体的长宽比,通常是使用画布的宽/画布的高。默认值是1 (正方形画布)
        camera.aspect = window.innerWidth / window.innerHeight;
        // 更新摄像机投影矩阵。在任何参数被改变以后必须被调用
        camera.updateProjectionMatrix();
        // 将输出canvas的大小调整为(width, height)并考虑设备像素比
        // 且将视口从(0, 0)开始调整到适合大小
        renderer.setSize( window.innerWidth, window.innerHeight );
    }

    function render() { // 一上来调用 鼠标移动调用
        // 更新聚光灯辅助对象
        lightHelper.update();
        // 基于相机的投影矩阵更新辅助对象
        shadowCameraHelper.update();
        // 用相机(camera)渲染一个场景(scene)
        renderer.render( scene, camera );
    }

    init();
    render();
</script>

</body>

</html>

 参考

DEMO

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值