zoukankan      html  css  js  c++  java
  • Three.js入门

      

      什么是WebGL。WebGL是在浏览器中实现三维效果的一套规范。使用WebGL原生的API来写3D程序是一件非常痛苦的事情,幸好,有很多同行花业余时间写了一些WebGL开源框架,其中three.js就是非常优秀的一个。

      什么是threejs,很简单,你将它理解成three + js就可以了。three表示3D的意思,js表示javascript的意思。那么合起来,three.js就是使用javascript 来写3D程序的意思。

       three.js官网地址:https://threejs.org/

    记录两个git地址:

    https://github.com/josdirksen/learning-threejs  Three.js开发指南一书对应的源码

    https://github.com/mrdoob/three.js      对three.js的封装,更加强大。

    1.入门程序

      1 <!DOCTYPE html>
      2 
      3 <html>
      4 
      5 <head>
      6     <title>Example 01.02 - First Scene</title>
      7     <script type="text/javascript" src="../libs/three.js"></script>
      8     <style>
      9         body {
     10             /* set margin to 0 and overflow to hidden, to go fullscreen */
     11             margin: 0;
     12             overflow: hidden;
     13         }
     14     </style>
     15 </head>
     16 <body>
     17 
     18 <!-- Div which will hold the Output -->
     19 <div id="WebGL-output">
     20 </div>
     21 
     22 <!-- Javascript code that runs our Three.js examples -->
     23 <script type="text/javascript">
     24 
     25     // once everything is loaded, we run our Three.js stuff.
     26     function init() {
     27 
     28         // create a scene, that will hold all our elements such as objects, cameras and lights.
     29         var scene = new THREE.Scene();
     30 
     31         // create a camera, which defines where we're looking at.
     32         var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
     33 
     34         // create a render and set the size
     35         var renderer = new THREE.WebGLRenderer();
     36         renderer.setClearColorHex();
     37         renderer.setClearColor(new THREE.Color(0xEEEEEE));
     38         renderer.setSize(window.innerWidth, window.innerHeight);
     39 
     40         // show axes in the screen
     41         var axes = new THREE.AxisHelper(20);
     42         scene.add(axes);
     43 
     44         // create the ground plane
     45         var planeGeometry = new THREE.PlaneGeometry(60, 20);
     46         var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc});
     47         var plane = new THREE.Mesh(planeGeometry, planeMaterial);
     48 
     49         // rotate and position the plane
     50         plane.rotation.x = -0.5 * Math.PI;
     51         plane.position.x = 15;
     52         plane.position.y = 0;
     53         plane.position.z = 0;
     54 
     55         // add the plane to the scene
     56         scene.add(plane);
     57 
     58         // create a cube
     59         var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
     60         var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
     61         var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
     62 
     63         // position the cube
     64         cube.position.x = -4;
     65         cube.position.y = 3;
     66         cube.position.z = 0;
     67 
     68         // add the cube to the scene
     69         scene.add(cube);
     70 
     71         // create a sphere
     72         var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
     73         var sphereMaterial = new THREE.MeshBasicMaterial({color: 0x7777ff, wireframe: true});
     74         var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
     75 
     76         // position the sphere
     77         sphere.position.x = 20;
     78         sphere.position.y = 4;
     79         sphere.position.z = 2;
     80 
     81         // add the sphere to the scene
     82         scene.add(sphere);
     83 
     84         // position and point the camera to the center of the scene
     85         camera.position.x = -30;
     86         camera.position.y = 40;
     87         camera.position.z = 30;
     88         camera.lookAt(scene.position);
     89 
     90         // add the output of the renderer to the html element
     91         document.getElementById("WebGL-output").appendChild(renderer.domElement);
     92 
     93         // render the scene
     94         renderer.render(scene, camera);
     95     }
     96     window.onload = init;
     97 
     98 </script>
     99 </body>
    100 </html>

    结果:

    上面包含的物体:

     解释:

        28-38行代码:

      首先定义了场景(Scene)、摄像机(camera)和渲染器(renderer)对象。场景是一个容器,主要用于保存、跟踪所要渲染的物体和使用的光源,如果没有THEE.Scene对象,那么Three.js无法渲染任何对象。摄像机决定了能够在场景中看到什么。渲染器会基于摄像机的角度来计算场景对象在浏览器中会渲染成什么样子。最后WebGLRendere将会使用电脑显卡来渲染场景。(除了基于WebGL的渲染器还有基于画板和SVG的渲染器,不推荐使用,因为太消耗CPU)。

      上面代码,renderer.setClearColorHex(); renderer.setClearColor(new THREE.Color(0xEEEEEE)); 将场景的背景颜色设置为接近白色,renderer.setSize(window.innerWidth, window.innerHeight);设置场景的大小。如果将上面代码修改为下面代码再次查看效果:

          renderer.setClearColor(new THREE.Color(0xEEEE00));
            renderer.setSize(500, 500);

     40行-56行:

      到上面已经创建了空白的场景、渲染器和摄像机,但是没有渲染任何东西,40-56行的代码会添加轴和平面。

      var axes = new THREE.AxisHelper(20);创建了轴(axes)对象,参数指定了线条的长度,并调用scene.add方法将轴添加到场景中。

      接下来创建了平面plane,平面的创建分为两步。首先是要  new THREE.PlaneGeometry(60, 20); 来定义平面的大小,宽度指定为60、高度设置为20,除了设置宽度和高度,我们还需要设置平面的外观(比如颜色和透明度),在three.js中通过创建材质对象来设置平面的外观,例子中用  new THREE.MeshBasicMaterial({color: 0xcccccc});  创建了颜色为 0xcccccc 的基本材质(THREE.MeshBasicMaterial) ,然后 new THREE.Mesh(planeGeometry, planeMaterial);  将平面和材质合并到名为plane的网格对象中。在平面添加到场景之前,还需要设置平面的位置:先将平面绕x轴旋转90度,然后使用  position  属性指定在场景中位置。最后将平面添加到场景中。

        58-82行:

         使用同样的方式将方块和球体添加到平面。但是需要将线框(wireframe)属性设置为true,这样物体就不会被渲染为实体。如果 wireframe 设置为false,渲染为实体效果如下:

        

         84-94行:

         现在,所以物体都已经加载到场景中。之前也说了摄像机将决定看到哪些物体。在这段代码中,我们使用x,y,z属性来设置摄像机的位置。为了确保所要渲染的物体能够被摄像机拍到,我们使用lookAt方法指向场景的中心,默认状态下摄像机是指向(0,0,0)位置的。最后要做的就是将渲染结果添加到HTML的div元素中。最后告诉渲染器使用指定的摄像机来渲染场景。

      如果我们将摄像机的x轴的位置改为0,  camera.position.x = 0;  效果如下:

    补充:摄像机的位置决定了看到哪些物体,也就决定了角度。也可以通过set方法设置其位置,如下:

    camera.position.set(-30,48,30);

    其有很多方法,如下: (我们用webstorm编辑器的时候会自动提示)

    2.添加材质、光源和阴影效果

    <!DOCTYPE html>
    
    <html>
    
    <head>
        <title>Example 01.03 - Materials and light</title>
        <script type="text/javascript" src="../libs/three.js"></script>
        <script type="text/javascript" src="../libs/stats.js"></script>
        <script type="text/javascript" src="../libs/dat.gui.js"></script>
        <style>
            body {
                /* set margin to 0 and overflow to hidden, to go fullscreen */
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>
    
    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
    
        // once everything is loaded, we run our Three.js stuff.
        function init() {
    
            // create a scene, that will hold all our elements such as objects, cameras and lights.
            var scene = new THREE.Scene();
    
            // create a camera, which defines where we're looking at.
            var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
    
            // create a render and set the size
            var renderer = new THREE.WebGLRenderer();
    
            renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMapEnabled = true;
    
            // create the ground plane
            var planeGeometry = new THREE.PlaneGeometry(60, 20);
            var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
            var plane = new THREE.Mesh(planeGeometry, planeMaterial);
            plane.receiveShadow = true;
    
            // rotate and position the plane
            plane.rotation.x = -0.5 * Math.PI;
            plane.position.x = 15;
            plane.position.y = 0;
            plane.position.z = 0;
    
            // add the plane to the scene
            scene.add(plane);
    
            // create a cube
            var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
            var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
            var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
            cube.castShadow = true;
    
            // position the cube
            cube.position.x = -4;
            cube.position.y = 3;
            cube.position.z = 0;
    
            // add the cube to the scene
            scene.add(cube);
    
            var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
            var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
            var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
    
            // position the sphere
            sphere.position.x = 20;
            sphere.position.y = 4;
            sphere.position.z = 2;
            sphere.castShadow = true;
    
            // add the sphere to the scene
            scene.add(sphere);
    
            // position and point the camera to the center of the scene
            camera.position.x = -30;
            camera.position.y = 40;
            camera.position.z = 30;
            camera.lookAt(scene.position);
    
            // add spotlight for the shadows
            var spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-40, 60, -10);
            spotLight.castShadow = true;
            scene.add(spotLight);
    
            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(renderer.domElement);
    
            // call the render function
            renderer.render(scene, camera);
        }
        window.onload = init;
    
    
    </script>
    </body>
    </html>

    结果:

     2.1添加光源

            // add spotlight for the shadows
            var spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-40, 60, -10);
            spotLight.castShadow = true;
            scene.add(spotLight);

       通过THREE.SpotLight定义光源并从其位置( spotLight.position.set(-40, 60, -10);) 照射场景。如果这时候渲染场景我们看到的结果和没光源是一样的。因为不同的材质对光源的反应是不一样的。我们使用的基本材质(THREE.MeshBasicMaterial)不会对光源产生任何反应,基本材质只会使用指定的颜色来渲染物体。所以需要改变平面、球体、和立方体的材质为  THREE.MeshLambertMaterial  即可。Three.js中的材质THREE.MeshLambertMaterial 和  THREE.MeshPhongMaterial在渲染时会对光源产生反应。

    2.2  渲染阴影

      由于渲染阴影需要消耗大量的计算资源,默认情况Three.js不会渲染阴影,为了渲染阴影效果,我们需要作如下:

    renderer.shadowMapEnabled = true;   首先渲染器的此属性设为true告诉渲染器需要阴影效果。

    另外还要指定哪个物体投射阴影、哪个物体接受阴影。如下平面接受阴影,小球和方体发出阴影:

    plane.receiveShadow = true;
    cube.castShadow = true;
    sphere.castShadow = true;

    最后还要指定光源产生阴影,因为并不是所有的光源都能产生阴影,THREE.SpotLight是能产生阴影的,我们只需要将castShadow属性设置为true就可以将阴影渲染出来。

    3.场景动起来

       如果希望场景动起来,首先需要解决的问题是如何在特定的时间间隔重新渲染场景。原生的JS是通过setInterval(fun,interval)来实现的,这个方法的缺点是不管浏览器正在发生什么都会执行定时作业。

    1.引入  requestAnimationFrame(render);

      在这个方法中可以定义所有的绘画操作,浏览器会尽可能平滑、高效地进行绘制。使用这个  requestAnimationFrame(); 的方法很简单,只需要创建一个处理渲染的方法即可:

            function render() {
                ...
                // render using requestAnimationFrame
                requestAnimationFrame(render);
                renderer.render(scene, camera);
            }

      在render()方法中  requestAnimationFrame() 方法又一次被调用了,这样做的目的是保证会话能持续运行。接下来需要做的就是:场景创建完毕之后不再调用render.render()方法,而是调用render()方法来启动动画,代码如下:

     document.getElementById("Stats-output").appendChild(stats.domElement);
     render();

      这时候运行代码和之前是一样的,因为还没有为物体添加任何动画效果。在添加动画之前,我们先来介绍一个辅助库,这个库也是Three.js作者开发的,主要用于检测动画运行时的帧数。在动画运行时,该库可以在一个图片中显示画面每秒传输帧数。

      辅助库:

    <script type="text/javascript" src="../libs/stats.js"></script>

      界面添加元素:

    <div id="Stats-output"></div>

       初始化统计对象,并将该对象添加到<div>元素中:

            function initStats() {
    
                var stats = new Stats();
    
                stats.setMode(0); // 0: fps, 1: ms
    
                // Align top-left
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.left = '0px';
                stats.domElement.style.top = '0px';
    
                document.getElementById("Stats-output").appendChild(stats.domElement);
    
                return stats;
            }

      这里需要注意setMode()方法。如果参数设置为 0 ,那么我们检测的是画面每秒传输帧数(fps); 如果参数设置为1,那么我们检测的是画面渲染时间。一般统计fps(Frames Per Second)。为了使具有统计功能,需要在一开始调用initStats()方法。

    var stats = initStats();

      为了能够通知stats对象画面何时被重新渲染,我们在render()方法需要调用stats.update()方法:

            function render() {
                stats.update();
                // render using requestAnimationFrame
                requestAnimationFrame(render);
                renderer.render(scene, camera);
            }

     2.  旋转立方体和弹跳的小球

    <!DOCTYPE html>
    
    <html>
    
    <head>
        <title>Example 01.04 - Materials, light and animation</title>
        <script type="text/javascript" src="../libs/three.js"></script>
    
        <script type="text/javascript" src="../libs/stats.js"></script>
        <style>
            body {
                /* set margin to 0 and overflow to hidden, to go fullscreen */
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    
    <div id="Stats-output">
    </div>
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>
    
    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
    
        // once everything is loaded, we run our Three.js stuff.
        function init() {
    
            var stats = initStats();
    
            // create a scene, that will hold all our elements such as objects, cameras and lights.
            var scene = new THREE.Scene();
    
            // create a camera, which defines where we're looking at.
            var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
    
            // create a render and set the size
            var renderer = new THREE.WebGLRenderer();
    
            renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMapEnabled = true;
    
            // create the ground plane
            var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1);
            var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
            var plane = new THREE.Mesh(planeGeometry, planeMaterial);
            plane.receiveShadow = true;
    
            // rotate and position the plane
            plane.rotation.x = -0.5 * Math.PI;
            plane.position.x = 15;
            plane.position.y = 0;
            plane.position.z = 0;
    
            // add the plane to the scene
            scene.add(plane);
    
            // create a cube
            var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
            var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
            var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
            cube.castShadow = true;
    
            // position the cube
            cube.position.x = -4;
            cube.position.y = 3;
            cube.position.z = 0;
    
            // add the cube to the scene
            scene.add(cube);
    
            var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
            var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
            var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
    
            // position the sphere
            sphere.position.x = 20;
            sphere.position.y = 0;
            sphere.position.z = 2;
            sphere.castShadow = true;
    
            // add the sphere to the scene
            scene.add(sphere);
    
            // position and point the camera to the center of the scene
            camera.position.x = -30;
            camera.position.y = 40;
            camera.position.z = 30;
            camera.lookAt(scene.position);
    
            // add subtle ambient lighting
            var ambientLight = new THREE.AmbientLight(0x0c0c0c);
            scene.add(ambientLight);
    
            // add spotlight for the shadows
            var spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-40, 60, -10);
            spotLight.castShadow = true;
            scene.add(spotLight);
    
            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(renderer.domElement);
    
            // call the render function
            var step = 0;
            renderScene();
    
            function renderScene() {
                stats.update();
                // rotate the cube around its axes
                cube.rotation.x += 0.02;
                cube.rotation.y += 0.02;
                cube.rotation.z += 0.02;
    
                // bounce the sphere up and down
                step += 0.04;
                sphere.position.x = 20 + ( 10 * (Math.cos(step)));
                sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));
    
                // render using requestAnimationFrame
                requestAnimationFrame(renderScene);
                renderer.render(scene, camera);
            }
    
            function initStats() {
    
                var stats = new Stats();
    
                stats.setMode(0); // 0: fps, 1: ms
    
                // Align top-left
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.left = '0px';
                stats.domElement.style.top = '0px';
    
                document.getElementById("Stats-output").appendChild(stats.domElement);
    
                return stats;
            }
        }
        window.onload = init;
    </script>
    </body>
    </html>

    解释:

      立方体旋转:在每次调用 renderScene() 方法的时候使得每个坐标轴的ration属性加0.2,其效果就是立方体将围绕它的轴进行缓慢的旋转。

      旋转立方体改变的是rotation属性;而让小球弹跳起来,我们所要做的是修改球体在场景中的位置(position)属性,我们的目的是让小球依照一条好看的、光滑的曲线从一个地方跳到另一个地方,如下:

      实现上面效果需要同时改变球体的x轴和y轴的位置,Math.cos()和Math.sin()方法使用step变量就可以创建出球体的运行轨迹。step+=0.4定义了球体的弹跳速度。

    3.使用dat.GUI简化实验流程

      这个库可以很容易地创建出能够改变代码变量的界面组件。

      像引入统计对象一样,我们需要引入类库:

    <script type="text/javascript" src="../libs/dat.gui.js"></script>

      接下来定义一个JS对象,该对象希望通过dat.GUI改变的属性。在JS代码中添加如下JS对象:

            var controls = new function () {
                this.rotationSpeed = 0.02;
                this.bouncingSpeed = 0.03;
            };

      在上面对象中定义了两个属性---rotationSpeed、bouncingSpeed以及它们的默认值,接下来需要将这个JS对象传递给data.GUI对象,并设置这两个属性的取值范围:

            var gui = new dat.GUI();
            gui.add(controls, 'rotationSpeed', 0, 0.5);
            gui.add(controls, 'bouncingSpeed', 0, 0.5);

      立方体旋转速度和球体弹跳速度的取值范围为0-0.5。现在需要在 render  中直接引用这两个属性,这样当我们在dat.GUI中修改这两个属性的值时就可以影响到相应的物体的旋转速度和弹跳速度,如下:

            function render() {
                stats.update();
                // rotate the cube around its axes
                cube.rotation.x += controls.rotationSpeed;
                cube.rotation.y += controls.rotationSpeed;
                cube.rotation.z += controls.rotationSpeed;
    
                // bounce the sphere up and down
                step += controls.bouncingSpeed;
                sphere.position.x = 20 + ( 10 * (Math.cos(step)));
                sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));
    
                // render using requestAnimationFrame
                requestAnimationFrame(render);
                renderer.render(scene, camera);
            }

    运行效果如下:

    4.场景对浏览器的自适应

       当浏览器大小改变时改变摄像机很容易实现。首先需要为浏览器注册一个事件监听器,如下:

        // listen to the resize events
        window.addEventListener('resize', onResize, false);

      这样,当浏览器尺寸改变时onResize()会被执行。在onResize()方法中需要更新摄像机和渲染器,如下:

        function onResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }

      对于摄像机,需要更新它的aspect属性,这个属性表示屏幕的长宽比;对于渲染器,需要改变它的尺寸。

    例如:

    <!DOCTYPE html>
    
    <html>
    
    <head>
        <title>Example 01.06 - Screen size change</title>
        <script type="text/javascript" src="../libs/three.js"></script>
        <script type="text/javascript" src="../libs/stats.js"></script>
        <script type="text/javascript" src="../libs/dat.gui.js"></script>
        <style>
            body {
                /* set margin to 0 and overflow to hidden, to go fullscreen */
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    
    <div id="Stats-output">
    </div>
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>
    
    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
    
        var camera;
        var scene;
        var renderer;
    
        // once everything is loaded, we run our Three.js stuff.
        function init() {
    
            var stats = initStats();
    
            // create a scene, that will hold all our elements such as objects, cameras and lights.
            scene = new THREE.Scene();
    
            // create a camera, which defines where we're looking at.
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
    
            // create a render and set the size
            renderer = new THREE.WebGLRenderer();
    
            renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMapEnabled = true;
    
            // create the ground plane
            var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1);
            var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
            var plane = new THREE.Mesh(planeGeometry, planeMaterial);
            plane.receiveShadow = true;
    
            // rotate and position the plane
            plane.rotation.x = -0.5 * Math.PI;
            plane.position.x = 15;
            plane.position.y = 0;
            plane.position.z = 0;
    
            // add the plane to the scene
            scene.add(plane);
    
            // create a cube
            var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
            var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
            var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
            cube.castShadow = true;
    
            // position the cube
            cube.position.x = -4;
            cube.position.y = 3;
            cube.position.z = 0;
    
            // add the cube to the scene
            scene.add(cube);
    
            var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
            var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
            var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
    
            // position the sphere
            sphere.position.x = 20;
            sphere.position.y = 0;
            sphere.position.z = 2;
            sphere.castShadow = true;
    
            // add the sphere to the scene
            scene.add(sphere);
    
            // position and point the camera to the center of the scene
            camera.position.x = -30;
            camera.position.y = 40;
            camera.position.z = 30;
            camera.lookAt(scene.position);
    
            // add subtle ambient lighting
            var ambientLight = new THREE.AmbientLight(0x0c0c0c);
            scene.add(ambientLight);
    
            // add spotlight for the shadows
            var spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-40, 60, -10);
            spotLight.castShadow = true;
            scene.add(spotLight);
    
            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(renderer.domElement);
    
            // call the render function
            var step = 0;
    
            var controls = new function () {
                this.rotationSpeed = 0.02;
                this.bouncingSpeed = 0.03;
            };
    
            var gui = new dat.GUI();
            gui.add(controls, 'rotationSpeed', 0, 0.5);
            gui.add(controls, 'bouncingSpeed', 0, 0.5);
    
            render();
    
            function render() {
                stats.update();
                // rotate the cube around its axes
                cube.rotation.x += controls.rotationSpeed;
                cube.rotation.y += controls.rotationSpeed;
                cube.rotation.z += controls.rotationSpeed;
    
                // bounce the sphere up and down
                step += controls.bouncingSpeed;
                sphere.position.x = 20 + ( 10 * (Math.cos(step)));
                sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));
    
                // render using requestAnimationFrame
                requestAnimationFrame(render);
                renderer.render(scene, camera);
            }
    
            function initStats() {
    
                var stats = new Stats();
    
                stats.setMode(0); // 0: fps, 1: ms
    
                // Align top-left
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.left = '0px';
                stats.domElement.style.top = '0px';
    
                document.getElementById("Stats-output").appendChild(stats.domElement);
    
                return stats;
            }
        }
        function onResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }
    
    
        window.onload = init;
    
        // listen to the resize events
        window.addEventListener('resize', onResize, false);
    
    </script>
    </body>
    </html>

    补充:Three.js用的是右手坐标系,看起来是这样的:

    总结:

      了解到three.js的3个基本组件:场景(scene)、相机(camera)、渲染器(render),以及其基本使用。场景是一个容器,主要用于保存、跟踪所要渲染的物体和使用的光源,如果没有THEE.Scene对象,那么Three.js无法渲染任何对象。摄像机决定了能够在场景中看到什么,其位置也决定了渲染的角度。渲染器会基于摄像机的角度来计算场景对象在浏览器中会渲染成什么样子。

      也学习了两个调试组件:stats监控帧数和dat.GUI创建能够改变代码变量的界面组件。GUI界面显示与隐藏的快捷键是H。

  • 相关阅读:
    webMagic学习笔记 主页
    maven 听视频笔记
    idea如何做到多模块开发项目 收藏整理
    JAVA 增删改查接口命名规范(dao层与 service 层
    mybatis 自学笔记
    nginx学习主页导航
    用 async/await 来处理异步
    若依:SysUserMapper.xml 分析
    idea 创建多模块项目子模块为灰色
    Maven多模块开发遇到的错误 -- Maven的子模块变成灰色
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/10824453.html
Copyright © 2011-2022 走看看