【ThreeJS基础教程-初识Threejs】1.2 控制面板 lil.gui 和帧率检测器stats

2024-7-27更新
本文原标题名:掌控我们的物体和模型
本文新标题名:控制面板 lil.gui 和帧率检测器stats
追加了部分对lil.gui和stats的说明

引入帧数监控与调试时使用的GUI

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas{
            display: block;
        }
        body {
            margin: 0;
            overscroll-behavior: none;
        }
        #btns{
            position: absolute;
            top:10%;
            width: 500px;
            height: 100px;
            left: 50%;
            transform:translateX(-50%);
        }
    </style>
</head>
<body>
<div id="btns"></div>

<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>

<script type="importmap">
			{
				"imports": {
					"three": "../three.js-master/build/three.module.js"
				}
			}
		</script>
<script type="module">
    import * as THREE from '../three.js-master/build/three.module.js';
    import {OrbitControls} from "../three.js-master/examples/jsm/controls/OrbitControls.js";
    import {GUI} from "../three.js-master/examples/jsm/libs/lil-gui.module.min.js"
    import Stats from "../three.js-master/examples/jsm/libs/stats.module.js"

    let scene,renderer,camera,orbitControls;

    let stats,gui;

    let mesh;

    function init(){
        scene = new THREE.Scene();
        renderer = new THREE.WebGLRenderer({
            alpha:true,
            antialias:true
        });
        renderer.setSize(window.innerWidth,window.innerHeight);
        document.body.appendChild(renderer.domElement);
        camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,1000);
        camera.position.set(10,10,10);
        orbitControls = new OrbitControls(camera,renderer.domElement);
        let helper = new THREE.GridHelper(50,10);
        scene.add(helper);

        stats= new Stats();
        document.body.appendChild(stats.dom);
        gui = new GUI();
    }
    function addMesh(){
        let geometry = new THREE.BoxGeometry(1,1,1);
        let material = new THREE.MeshBasicMaterial({
            color:"#ff0000"
        });
        mesh = new THREE.Mesh(geometry,material);
        scene.add(mesh);
    }

    function addGUI() {
        gui.add(mesh.position,"x",-10,10).step(0.5).name("位置x");
        gui.add(mesh.position,"y",-10,10).step(0.5).name("位置y");
        gui.add(mesh.position,"z",-10,10).step(0.5).name("位置z");

        let params = {
            rx:0,
            ry:0,
            rz:0
        };

        gui.add(params,"rx",-Math.PI,Math.PI).step(Math.PI/180).name("旋转x").onChange((value)=>{
            mesh.rotation.x = params.rx;
        });
        gui.add(params,"ry",-Math.PI,Math.PI).step(Math.PI/180).name("旋转y").onChange((value)=>{
            mesh.rotation.y = params.ry;
        });
        gui.add(params,"rz",-Math.PI,Math.PI).step(Math.PI/180).name("旋转z").onChange((value)=>{
            mesh.rotation.z = params.rz;
        });

    }

    function render(){
        renderer.render(scene,camera);
        requestAnimationFrame(render);
        stats.update();
    }
    init();
    addMesh();
    addGUI();
    render();
</script>
</body>
</html>

案例效果
在这里插入图片描述

当你运行案例时,你发现,左上角有了一个小窗口,并且显示着你的当前刷新率,笔者这里使用的是144hz的屏幕,所以显示的刷新率为144,常见刷新率为60,75,120,144等
刷新率会直接反馈给你你的项目运行是否卡顿,如果你的显示器常驻刷新率是60帧,当你加载了过于复杂的模型后,你的帧率降到了60以下,甚至低于30的时候,那么,这个模型在你的设备和同等级及以下水平的设备下运行,会降低用户的实际使用体验

一般来说,做WebGL项目要考虑最低的设备等级,你的用户群如果是全民,那么你在开发时,就应考虑【如何使最低配置的设备能流畅运行你的程序】,左上角的这个插件,就是一个很好的检测程序运行流畅度的插件

右上角多了一个比较大的窗口,你发现,拖动中间的蓝色小杆,让它左右移动,可以让中间的模型发生变化,比如位置x,可以让模型沿着x轴移动,旋转x可以让模型沿着x轴旋转等

其他功能均与上一个案例一致

案例解析

多数代码已经在上一篇解析完毕,本篇仅针对新出现的代码进行解析

引入刷新率检测器stats和lil-gui

在这里插入图片描述
文件位置如图所示,对应的ES5版本在examples/js/libs/下

    import {GUI} from "../three.js-master/examples/jsm/libs/lil-gui.module.min.js"
    import Stats from "../three.js-master/examples/jsm/libs/stats.module.js"

	let stats,gui;

	function init(){
		......
		stats= new Stats();
		document.body.appendChild( stats.dom );
		gui = new GUI();
	}
	...
	render(){
		......
		stats.update();
	}

按上述写法引入对应的这两个文件后,先全局创建对应的变量,然后在初始化阶段初始化它们即可

Stats

构造器:new Stats() 没啥说的,就是一个new,创建完记得把dom添加到你的html中,上述代码是添加到了body中 ,添加后,你的左上角就会出现上面效果图中的刷新率检测方块
函数:stats.update(); 因为这个东西要时刻检测帧率,所以需要放到requestAnimationFrame绑定的函数中,否则不会生效

左上角的方块有三种模式,使用鼠标点击方块即可切换,目前我们仅使用蓝色的即可

帧率检测器的主要目的是帮助我们判断当前的项目是否正常渲染,用于判断显卡压力的工具,比如说你现在的屏幕刷新率是60,那么帧率显示器,应该显示到60帧,才说明你现在的显卡压力没有超过上限,你的项目不卡,一般来说,50~60帧的情况下,人眼是很难判断的,但是如果跌倒40帧,就很明显了,30帧和60帧就已经是明显卡顿了,如果你经常玩游戏就会明白,这个就是经常说的掉帧,掉帧意味着你的显卡已经不足以支撑现阶段的流畅渲染了,就需要优化项目了

LIL.GUI (Dat.GUI)

从不知道什么版本起,threejs从使用Dat.gui改成了使用lil.gui,两者的用法几乎一致,只是名字区别,所以使用习惯了Dat.gui的人基本上也可以无门槛入坑lil.gui
lil.gui的官网

温馨提醒,一般人不会用lil.gui上到最终的项目上。。。它不好看,这只是个开发时的优良辅助工具

构造器 new GUI() lil-gui,升级于Dat.GUI,如果想要找一套系统的使用教程,请搜索Dat.GUI,或者去lil-gui的github地址或官网,其中也有相关的文档和教程
lil-gui的官方网站 https://lil-gui.georgealways.com/
这个构造器相对来说就只new一下就ok了,右上角会直接出现一个黑色的小方框,但是,仅仅只new一个它,它什么也不会显示,会显示成这样
在这里插入图片描述

    function addGUI() {
        gui.add(mesh.position,"x",-10,10).step(0.5).name("位置x");
        gui.add(mesh.position,"y",-10,10).step(0.5).name("位置y");
        gui.add(mesh.position,"z",-10,10).step(0.5).name("位置z");

        let params = {
            rx:0,
            ry:0,
            rz:0
        };

        gui.add(params,"rx",-Math.PI,Math.PI).step(Math.PI/180).name("旋转x").onChange((value)=>{
            mesh.rotation.x = params.rx;
        });
        gui.add(params,"ry",-Math.PI,Math.PI).step(Math.PI/180).name("旋转y").onChange((value)=>{
            mesh.rotation.y = params.ry;
        });
        gui.add(params,"rz",-Math.PI,Math.PI).step(Math.PI/180).name("旋转z").onChange((value)=>{
            mesh.rotation.z = params.rz;
        });
    }

以上展示了两种,向GUI添加控制块的方法

方法1:直接操作物体的对应属性

gui.add(对象,属性名,属性值下限,属性值上限) 用于添加一个控制器
比如我这里,想要控制小方块的位置,那么:

我们的对象是:mesh.position ,positions一个THREE.Vector3对象,这里我们要拿到最小的对象
属性是:x,Vector3对象有三个基础属性,分别是x,y,z
属性值下限:默认为负无限大,但是我们做项目调试的话,尽量设置一个下限值和上限值
属性值上限:同上

接下来,我需要为它添加步长,拖动一下让物体移动多少距离
gui.add().step(0.5) 这样,我们在gui上拖动,每触发一次mousemove,方块会移动0.5个单位

英文的看不懂或者不会翻译怎么办?那我们添加一个中文的标签名
gui.add().name(“位置x”)

完整的写法下来就是
gui.add( mesh.position,“x”, -10, 10 ).step(0.5).name(“位置x”)

翻译下来为:
向GUI添加一组控制器,控制mesh(小方块)位置对象的x属性,使控制器可以将x这个属性值,修改为-10~10的数字,每一次操作会改变0.5的值,为控制块设定名称为:“位置x”

将x,y,z三个属性都添加了控制器之后,我们就可以使用GUI控制方块了

但是我们还有第二种写法

首先创建一个对象

	        let params = {
	            x:0,
	            y:0,
	            z:0
	        };

同样的方式,我们控制这个对象,而非直接控制模型的属性
gui.add( params,“x”, -10, 10 ).step(0.5).name(“位置x”)

这样我们并不能直接控制模型,我们还需要下一步操作

gui.add().onChange( function(value){} )

使用onChange函数,可以让我们的属性变的更实用

上面同样的段落,我们可以这样写

gui.add( params,"x", -10, 10 ).step(0.5).name("位置x").onChange( value=>{
	mesh.position.x = value;
} );

这样写的好处是,你可以用一个params控制多个属性,且逻辑上比较清晰

上面代码块中,关于mesh的旋转的控制,就是由gui控制param,进一步控制mesh.rotation来进行旋转的

ThreeJS中使用的旋转角度均为弧度制,代码中设置了下限为180度,在js中使用Math.PI来表示弧度制的180度,弧度制忘了的同学可以去搜一下做个基本复习

这样,添加旋转的那一部分代码就讲完了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值