Three.js中文网
<template>
<div id="webgl"></div>
</template>
<script setup>
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 创建3D场景对象Scene
const scene = new THREE.Scene();
//创建一个长方体几何对象Geometry
const geometry = new THREE.BoxGeometry(100, 60, 20);
//创建一个材质对象Material
const material = new THREE.MeshLambertMaterial({
color: 0xff0000,//0xff0000设置材质颜色为红色
transparent: true,//开启透明
opacity: 0.8,//设置透明度
});
// 两个参数分别为几何体geometry、材质material
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
//设置网格模型在三维空间中的位置坐标,默认是坐标原点
mesh.position.set(80, 0, 0);
scene.add(mesh);
// AxesHelper:辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(250); // 长度
scene.add(axesHelper);
// 环境光:没有特定方向,整体改变场景的光照明暗
// const ambient = new THREE.AmbientLight(0xffffff, 0.4);
// scene.add(ambient);
// 点光源
const pointLight = new THREE.PointLight(0xffffff, 1.0);
pointLight.position.set(80, 50, 50);//点光源放在x轴上
pointLight.intensity = 10000.0;//光照强度
scene.add(pointLight); //点光源添加到场景中
// 点光源辅助观察
const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
scene.add(pointLightHelper);
// 平行光
// const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// // 设置光源的方向:通过光源position属性和目标指向对象的position属性计算
// // directionalLight.position.set(80, 100, 50);
// directionalLight.position.set(100, 60, 50);
// // 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0
// directionalLight.target = mesh;
// scene.add(directionalLight);
// 可视化平行光辅助观察
// const dirLightHelper = new THREE.DirectionalLightHelper(directionalLight, 5,0xff0000);
// scene.add(dirLightHelper);
// 实例化一个透视投影相机对象(fov 摄像机视锥体垂直视野角度45,aspect 摄像机视锥体长宽比width/height,near 摄像机视锥体近端面0.1,far 摄像机视锥体远端面1000)
const camera = new THREE.PerspectiveCamera();
// 相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(200, 200, 200);
// 相机观察目标指向Threejs 3D空间中某个位置(相机看向的地方)
camera.lookAt(0, 0, 0); // 坐标原点(可自定义)
// camera.lookAt(mesh.position);// 指向mesh对应的位置
// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();
// 定义threejs输出画布的尺寸(单位:像素px)
const width = window.innerWidth; //宽度
const height = window.innerHeight; //高度
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
renderer.render(scene, camera);
document.body.appendChild(renderer.domElement);
// 渲染循环
const clock = new THREE.Clock();
function render() {
const spt = clock.getDelta() * 1000;//毫秒
console.log('两帧渲染时间间隔(毫秒)', spt);
console.log('帧率FPS', 1000 / spt);
renderer.render(scene, camera); //执行渲染操作
mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render);//请求再次执行渲染函数render,渲染下一帧
}
render();
// 设置了渲染循环,相机控件OrbitControls就不用再通过事件change执行renderer.render(scene, camera);,毕竟渲染循环一直在执行renderer.render(scene, camera);
// 设置相机控件轨道控制器OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
// 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景
controls.addEventListener('change', function () {
renderer.render(scene, camera); //执行渲染操作
// 浏览器控制台查看相机位置变化
console.log('camera.position', camera.position);
}); // 监听鼠标、键盘事件
// onresize 事件会在窗口被调整大小时发生
window.onresize = function () {
// 重置渲染器输出画布canvas尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
// 全屏情况下:设置观察范围长宽比aspect为窗口宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix
// 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源)
// 如果相机的一些属性发生了变化,需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
camera.updateProjectionMatrix();
};
</script>