第1话 使用帧率监测器和dat.gui来查看当前页面刷新的帧率

第一个threejs程序

<!DOCTYPE html>
<html>
<head>
<title>第一个threejs程序</title>
<script type="text/javascript" src="../libs/three.js"></script>
</head>
<body>
<div id="threejs-example">
</div>
<script type="text/javascript">
    function init() {
      
      
        // 新建场景
        var scene = new THREE.Scene();

        // 设置相机
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        // 构造渲染器,这里使用WebGL渲染器
        var renderer = new THREE.WebGLRenderer();
        // 设置背景色
        renderer.setClearColor(new THREE.Color(0xEEEEEE));
        renderer.setSize(window.innerWidth, window.innerHeight);

        // 向场景中添加坐标轴
        var axes = new THREE.AxisHelper(20);
        scene.add(axes);

        // 新建一个平面plane
        var planeGeometry = new THREE.PlaneGeometry(60, 20);    // 长60,宽20的平面
        var planeMaterial = new THREE.MeshBasicMaterial({
      
      color: 0xcccccc});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);

        // 确定平面坐标
        plane.rotation.x = -0.5 * Math.PI;  // 沿x轴旋转90度
        plane.position.x = 15;  // 在x,y,z三个方向上的偏移
        plane.position.y = 0;
        plane.position.z = 0;

        // 向场景中添加平面
        scene.add(plane);

        // 创建一个方块cube
        var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
        var cubeMaterial = new THREE.MeshBasicMaterial({
      
      color: 0xff0000, wireframe: true});  // 打开wireframe则可以看到物体的结构框架
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

        // 确定方块坐标
        cube.position.x = -4;
        cube.position.y = 3;
        cube.position.z = 0;

        scene.add(cube);

        // 创建一个球体sphere
        var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
        var sphereMaterial = new THREE.MeshBasicMaterial({
      
      color: 0x7777ff, wireframe: true});
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

        // 确定球体位置
        sphere.position.x = 20;
        sphere.position.y = 4;
        sphere.position.z = 2;

        // 向场景中添加球体
        scene.add(sphere);

        // 确定相机位置
        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);      // 使用lookAt()函数将相机指向场景的中心

        document.getElementById("threejs-example").appendChild(renderer.domElement);
        renderer.render(scene, camera);     // 渲染场景
    }
    window.onload = init;
</script>
</body>
</html>

请添加图片描述

渲染阴影——添加光源并更改材质

MeshBasicMaterial基本材质不能对场景中的光源产生反应,它只能按照指定的颜色渲染物体,threejs中提供了两种材质可以对光源产生反应——MeshLambertMaterial和MeshPhongMaterial材质。

由于渲染阴影要消耗大量的计算资源,因此默认情况下threejs并不生成阴影。
要使threejs渲染出阴影效果,除了打开threejs的阴影渲染许可(renderer.shadowMapEnabled = true)外,还要确定哪些物体是接收阴影的,哪些物体是发出阴影的,分别打开相应物体Mesh对象的receiveShadow和castShadow设置。

另外,还要使场景中的光源渲染出阴影。

<!DOCTYPE html>
<html>
<head>
<title>第一个threejs程序</title>
<script type="text/javascript" src="../libs/three.js"></script>
</head>
<body>
<div id="threejs-example"></div>
<script type="text/javascript">
    function init() {
    
    
        var scene = new THREE.Scene();

        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        var renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(new THREE.Color(0xEEEEEE));
        renderer.setSize(window.innerWidth, window.innerHeight);

         // 使threejs允许场景渲染出阴影(由于渲染阴影要消耗大量的计算资源,因此默认情况下threejs并不生成阴影)
         renderer.shadowMapEnabled = true;

        var axes = new THREE.AxisHelper(20);
        scene.add(axes);

        // 新建一个平面plane
        var planeGeometry = new THREE.PlaneGeometry(60, 20);    // 设置物体材质为MeshLambertMaterial,它可以对光源做出反应
        var planeMaterial = new THREE.MeshLambertMaterial({
    
    color: 0xcccccc});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);

        plane.rotation.x = -0.5 * Math.PI;
        plane.position.x = 15;
        plane.position.y = 0;
        plane.position.z = 0;
        plane.receiveShadow = true;

        scene.add(plane);

        // 创建一个方块cube
        var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
        // var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
        var cubeMaterial = new THREE.MeshLambertMaterial({
    
    color: 0xff0000});
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

        // 确定方块坐标
        cube.position.x = -4;
        cube.position.y = 3;
        cube.position.z = 0;
        cube.castShadow = true;     // 可以发出阴影

        scene.add(cube);

        // 创建一个球体sphere
        var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
        var sphereMaterial = new THREE.MeshLambertMaterial({
    
    color: 0x7777ff});
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

        sphere.position.x = 20;
        sphere.position.y = 4;
        sphere.position.z = 2;
        sphere.castShadow = true;

        scene.add(sphere);

        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);  // 使用lookAt函数将相机指向场景的中心

        // 向场景中添加光源
        var spotLight = new THREE.SpotLight( 0xffffff );
        spotLight.position.set( -40, 60, -10 );
        spotLight.castShadow = true;                // 让聚光灯光源发出阴影
        scene.add(spotLight);

        document.getElementById("threejs-example").appendChild(renderer.domElement);
        renderer.render(scene, camera);
    }
    window.onload = init;
</script>
</body>
</html>

请添加图片描述

持续渲染场景和开启渲染帧率监测器stats

可以利用requestAnimationFrame()写一个函数renderScene()达到持续渲染场景的效果,而要开启渲染帧率监测器,则需要引入stats.js,初始化stats对象后,需要在renderScene()函数中使用update()更新帧率。

<!DOCTYPE html>
<html>
<head>
<title>第一个threejs程序</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
</head>
<body>

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

<script type="text/javascript">
    function init() {
      
      
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        var renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(new THREE.Color(0xEEEEEE));
        renderer.setSize(window.innerWidth, window.innerHeight);

         renderer.shadowMapEnabled = true;

        var axes = new THREE.AxisHelper(20);
        scene.add(axes);

        // 新建一个平面plane
        var planeGeometry = new THREE.PlaneGeometry(60, 20);
        var planeMaterial = new THREE.MeshLambertMaterial({
      
      color: 0xcccccc});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);

        plane.rotation.x = -0.5 * Math.PI;
        plane.position.x = 15;
        plane.position.y = 0;
        plane.position.z = 0;
        plane.receiveShadow = true;

        scene.add(plane);

        var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
        var cubeMaterial = new THREE.MeshLambertMaterial({
      
      color: 0xff0000});
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

        cube.position.x = -4;
        cube.position.y = 3;
        cube.position.z = 0;
        cube.castShadow = true;

        scene.add(cube);

        // 创建一个球体sphere
        var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
        var sphereMaterial = new THREE.MeshLambertMaterial({
      
      color: 0x7777ff});
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

        sphere.position.x = 20;
        sphere.position.y = 4;
        sphere.position.z = 2;
        sphere.castShadow = true;

        scene.add(sphere);

        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);

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

        document.getElementById("threejs-example").appendChild(renderer.domElement);

        // 利用requestAnimationFrame()写一个函数达到持续渲染场景的效果
        var stats = initStats();    // stats的初始化必须在renderScene()调用之前(因为renderScene()函数中要使用stats实例对象)
        renderScene();

        function renderScene() {
      
      
            stats.update();   // 刷新帧率
            renderer.render(scene, camera);
            requestAnimationFrame(renderScene);
        }

        function initStats() {
      
      
            // 初始化帧率监测器
            var stats = new Stats();

            stats.setMode(0); // 模式值: 0: fps, 1: ms

            // 把帧率监测器放在屏幕的左边
            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()函数中添加更改方块旋转角度和更改球体坐标的代码,即可实现动画。

<!DOCTYPE html>
<html>
<head>
<title>第一个threejs程序</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
</head>
<body>

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

<script type="text/javascript">
    function init() {
      
      
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        var renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(new THREE.Color(0xEEEEEE));
        renderer.setSize(window.innerWidth, window.innerHeight);

         renderer.shadowMapEnabled = true;

        var axes = new THREE.AxisHelper(20);
        scene.add(axes);

        // 新建一个平面plane
        var planeGeometry = new THREE.PlaneGeometry(60, 20);
        var planeMaterial = new THREE.MeshLambertMaterial({
      
      color: 0xcccccc});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);

        plane.rotation.x = -0.5 * Math.PI;
        plane.position.x = 15;
        plane.position.y = 0;
        plane.position.z = 0;
        plane.receiveShadow = true;

        scene.add(plane);

        var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
        var cubeMaterial = new THREE.MeshLambertMaterial({
      
      color: 0xff0000});
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

        cube.position.x = -4;
        cube.position.y = 3;
        cube.position.z = 0;
        cube.castShadow = true;

        scene.add(cube);

        // 创建一个球体sphere
        var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
        var sphereMaterial = new THREE.MeshLambertMaterial({
      
      color: 0x7777ff});
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

        sphere.position.x = 20;
        sphere.position.y = 4;
        sphere.position.z = 2;
        sphere.castShadow = true;

        scene.add(sphere);

        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);

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

        document.getElementById("threejs-example").appendChild(renderer.domElement);

        var stats = initStats();
        renderScene();
        var step = 0;
        function renderScene() {
      
      
            stats.update();

            // 方块旋转
            cube.rotation.x += 0.02;
            cube.rotation.y += 0.02;
            cube.rotation.z += 0.02;

            // 弹跳球
            step += 0.04;   // 弹跳速度
            sphere.position.x = 20+( 10* Math.cos(step) );
            sphere.position.y = 2 + ( 10*Math.abs(Math.sin(step)));

            renderer.render(scene, camera);
            requestAnimationFrame(renderScene);
        }

        function initStats() {
      
      
            var stats = new Stats();
            stats.setMode(0);

            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>

请添加图片描述

使用dat.GUI库

通过引入dat.gui.js库来生成一个控制界面,通过滑动条来控制方块的旋转速度和球体的弹跳速度。

<!DOCTYPE html>
<html>
<head>
<title>第一个threejs程序</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>
</head>
<body>

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

<script type="text/javascript">
    function init() {
      
      
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        var renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(new THREE.Color(0xEEEEEE));
        renderer.setSize(window.innerWidth, window.innerHeight);

        renderer.shadowMapEnabled = true;

        var axes = new THREE.AxisHelper(20);
        scene.add(axes);

        // 新建一个平面plane
        var planeGeometry = new THREE.PlaneGeometry(60, 20);
        var planeMaterial = new THREE.MeshLambertMaterial({
      
      color: 0xcccccc});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);

        plane.rotation.x = -0.5 * Math.PI;
        plane.position.x = 15;
        plane.position.y = 0;
        plane.position.z = 0;
        plane.receiveShadow = true;

        scene.add(plane);

        var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
        var cubeMaterial = new THREE.MeshLambertMaterial({
      
      color: 0xff0000});
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

        cube.position.x = -4;
        cube.position.y = 3;
        cube.position.z = 0;
        cube.castShadow = true;

        scene.add(cube);

        // 创建一个球体sphere
        var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
        var sphereMaterial = new THREE.MeshLambertMaterial({
      
      color: 0x7777ff});
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

        sphere.position.x = 20;
        sphere.position.y = 4;
        sphere.position.z = 2;
        sphere.castShadow = true;

        scene.add(sphere);

        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);

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

        document.getElementById("threejs-example").appendChild(renderer.domElement);

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

        var gui = new dat.GUI();
        gui.add(controls, 'rotationSpeed', 0, 0.5); // 取值范围是0 -- 0.5
        gui.add(controls, 'bouncingSpeed', 0, 0.5); // GUI控制变量bouncingSpeed的取值

        var stats = initStats();
        var step = 0;

        renderScene();      // 在renderScene()函数中使用到的变量必须在调用点之前被定义
        function renderScene() {
      
      
            stats.update();

            // 使用dat.GUI控制方块的旋转速度
            cube.rotation.x += controls.rotationSpeed;
            cube.rotation.y += controls.rotationSpeed;
            cube.rotation.z += controls.rotationSpeed;

            // 使用dat.GUI控制球的弹跳速度
            step += controls.bouncingSpeed;
            sphere.position.x = 20 + ( 10 * (Math.cos(step)));
            sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));

            renderer.render(scene, camera);
            requestAnimationFrame(renderScene);
        }

        function initStats() {
      
      
            var stats = new Stats();
            stats.setMode(0);

            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>

请添加图片描述

猜你喜欢

转载自blog.csdn.net/qq_39153720/article/details/121218923
今日推荐