threejs入门,GUI控制与动画

threejs简介

threejs用于构建3D相关的应用,是对webGL的上层封装,功能强大不必多说,今天简单入门一下吧。

推荐学习网站

简单应用

以下应用基于Vue3

引入

<template>
  <div id="webgl"></div>
</template>
<script setup>
import { onMounted } from "vue";
import * as THREE from 'three'
</script>

声明

let scene, camera, mesh, controls, material, geometry
let renderer

基础原理说明

简单地说,threejs的4个基本体就是:

  • 网格模型mesh
  • 相机camera
  • 场景scene
  • 渲染器renderer
    然后就是每个基本体的细分与配置,如:
    网格模型由几何体geometry材质material组成
    相机常用的有正投影相机透视投影相机
    场景scene中可以添加多个网格实例
    几何体又分为立方体球体锥体
    然后就是一些光线辅助线GUI加载器等内容。
    说难不难,说简单也不简单,主要还得在实际应用中提升。

创建过程

创建3D场景对象
 scene = new THREE.Scene();
创建一个长方体几何对象
geometry = new THREE.BoxGeometry(100, 100, 100);
创建一个材质对象Material
  material = new THREE.MeshBasicMaterial({
    color: 0xff9999,//0xff9999设置材质颜色为红色
    transparent: true,//开启透明
    opacity: 0.1,//设置透明度
  });
创建并配置网格模型
const meshObj = {
  x: 0,
  y: 10,
  z: 0
}
mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
// 设置网格模型在三维空间中的位置坐标,默认是坐标原点
mesh.position.set(meshObj.x, meshObj.y, meshObj.z);
添加到场景
scene.add(mesh);
创建辅助观察的坐标系
  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);
创建光源和辅助光源观察
 const pointLight = new THREE.PointLight(0xffffff, 1.0);
  pointLight.intensity = 1.0;//光照强度
  pointLight.decay = 0.0;//设置光源不随距离衰减
  pointLight.position.set(400, 0, 0);//点光源放在x轴上
  scene.add(pointLight); //点光源添加到场景中

  // 光源辅助观察
  const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
  scene.add(pointLightHelper);
  // pointLight.position.set(100, 60, 50);
  pointLight.position.set(-400, -200, -300);
环境光
 //环境光:没有特定方向,整体改变场景的光照明暗
  const ambient = new THREE.AmbientLight(0xffffff, 0.4);
  scene.add(ambient);
平行光
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  // 设置光源的方向:通过光源position属性和目标指向对象的position属性计算
  directionalLight.position.set(80, 100, 50);
  // 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0
  directionalLight.target = mesh;
  scene.add(directionalLight);
设置画布容器
const webglContainer = document.querySelector('#webgl');
// 定义相机输出画布的尺寸(单位:像素px)
const width = webglContainer.clientWidth; //窗口文档显示区的宽度作为画布宽度
const height = window.innerHeight; //窗口文档显示区的高度作为画布高度
创建配置相机
  camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);

  // 相机在Three.js三维坐标系中的位置
  // 根据需要设置相机位置具体值
  camera.position.set(200, 200, 200);
  camera.lookAt(mesh.position);//指向mesh对应的位置
创建渲染器
  // 创建渲染器对象
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
  renderer.render(scene, camera); //执行渲染操作
创建控制器
  // 设置相机控件轨道控制器OrbitControls
  controls = new OrbitControls(camera, renderer.domElement);
  // 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景
  controls.addEventListener('change', function () {
    renderer.render(scene, camera); //执行渲染操作
  });//监听鼠标、键盘事件
添加窗口改变事件
window.onresize = function () {
  // 重置渲染器输出画布canvas尺寸  window.innerWidth
  renderer.setSize(webglContainer.clientWidth, window.innerHeight);
  // 全屏情况下:设置观察范围长宽比aspect为窗口宽高比
  camera.aspect = webglContainer.clientWidth / window.innerHeight;
  // 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix
  // 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源)
  // 如果相机的一些属性发生了变化,需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
  camera.updateProjectionMatrix();
};
渲染重复执行的动画
function render() {
  renderer.render(scene, camera); //执行渲染操作
  mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
  requestAnimationFrame(render);//请求再次执行渲染函数render,渲染下一帧
}
效果预览

上述代码会产生一个沿着y轴不断旋转的立方体
在这里插入图片描述

添加GUI控制器

此外,还可以添加GUI控制器

import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
let gui;

gui = new GUI();

gui.domElement.style.right = '0px';
gui.domElement.style.width = '300px';

gui.add(mesh.position, 'x', 0, 180).onChange(e => {
  console.log('x', e)
  render()
});
gui.add(mesh.position, 'y', 0, 180).onChange(e => {
  console.log('y', e)
  render()
});
gui.add(mesh.position, 'z', 0, 180).onChange(e => {
  console.log('z', e)
  render()
});

效果如下
在这里插入图片描述
现在就可以用GUI来控制立方体的坐标位置了

其他

此外,还可以创建文本、贴图、3d模型等,需要进一步看下文档,本问仅作简单入门实例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值