Vue3+Three.js星空球体

结果图

在这里插入图片描述

threejs比例不变自适应

首先是设置相机和render,要注意的就是相机要加上aspect不然如果页面不是正方形看到的样式就会失调。

// ---------相机设置-------------
// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera();
//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
const cameraPostion = [20, 20, 20];
camera.position.set(...cameraPostion);
camera.lookAt(mesh.position);//指向mesh对应的位置
// 更新相机的宽高比
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();// ----------渲染器设置------------
// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();
// 定义threejs输出画布的尺寸(单位:像素px)
const width = window.innerWidth; //宽度
const height = window.innerHeight; //高度
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
// renderer.setPixelRatio(window.devicePixelRatio)
renderer.render(scene, camera); //执行渲染操作

在onmounted中加入resize事件的监听,这样即使缩放也不会又问题

window.addEventListener('resize', () => {const width = window.innerWidth; //宽度const height = window.innerHeight; //高度// camera.position.set(20, 20, 20);camera.lookAt(mesh.position);//指向mesh对应的位置// 更新相机的宽高比camera.aspect = width / height;// 更新摄像机的投影矩阵camera.updateProjectionMatrix();renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)renderer.render(scene, camera); //执行渲染操作});

鼠标控制视角

禁止拖拽和缩放是为了以防超出天空盒或者进入地球模型中,也可以设置这两个的范围

const controls = new MapControls(camera, renderer.domElement);
controls.enablePan = false; //禁止右键拖拽
controls.enableZoom = false;//禁止缩放
controls.addEventListener('change', function () {// 鼠标右键旋转时候,查看.position变化// 鼠标左键拖动的时候,查看.position、.target的位置会变化console.log('camera.position', camera.position);renderer.render(scene, camera); //执行渲染操作// console.log('controls.target', controls.target);
});

天空盒

这边我采用了球体来制作天空盒,因为cube要6张图很难找,刚好我看到了一个长图,就直接用了

//----------天空盒-----------
// 加载天空球纹理
// 创建TextureLoader加载天空盒纹理
let texture = new THREE.TextureLoader().load([require('../assets/longbk.jpeg')
]);
// 创建立方体几何体并应用天空盒材质
createGeometry(scene, 'Sphere', [500], [0, 0, 0],{map: texture, //设置材质环境贴图side: THREE.DoubleSide // 双面展示}
)

记得天空盒是需要双面贴图的,因为视角在里面,不然是看不见贴图的

遇到的问题以及一些补充

【2024/1/3】------ 之前的代码没有添加动画会导致刚打开的瞬间是黑屏的,因为加载texture是异步的,这个问题我一开始没有找到解决办法加个setTimeout什么的都不行,放在里面做回调函数也不行,知道我发现了只要加上动画就可以及时添加texture,如下

function render() {// i+=1;// console.log('执行次数'+i);renderer.render(scene, camera); //执行渲染操作requestAnimationFrame(render);//请求再次执行函数render
}
render();

具体代码

<template><div><div ref="webgl"></div></div>
</template><script setup>
// 引入three.js
import * as THREE from 'three';
import { createGeometry } from '../utils/threeFun.js'
import { onMounted, ref } from 'vue';
// 引入相机控件`MapControls`
import { MapControls } from 'three/addons/controls/OrbitControls.js';
// 引入dat.gui.js的一个类GUI
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';const webgl = ref(null);// 创建3D场景对象Scene
const scene = new THREE.Scene();// // ----------场景布置------------
let earthTexture = new THREE.TextureLoader().load([require('../assets/earth.jpg')
]);
let mesh = createGeometry(scene, 'Sphere', [5], [0, 0, 0], {map: earthTexture,// color: 0xff0000,//0xff0000设置材质颜色为红色
})//=========测试用===========
// AxesHelper:辅助观察的坐标系 
// const axesHelper = new THREE.AxesHelper(200)
// scene.add(axesHelper)//----------天空盒-----------
// 加载天空球纹理
// 创建TextureLoader加载天空盒纹理
let texture = new THREE.TextureLoader().load([require('../assets/longbk.jpeg')
]);
// 创建立方体几何体并应用天空盒材质
createGeometry(scene, 'Sphere', [50], [0, 0, 0],{map: texture, //设置材质环境贴图side: THREE.DoubleSide // 双面展示}
)// ---------相机设置-------------
// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera();
//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
const cameraPostion = [20, 20, 20];
camera.position.set(...cameraPostion);
camera.lookAt(mesh.position);//指向mesh对应的位置
// 更新相机的宽高比
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();// ----------渲染器设置------------
// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();
// 定义threejs输出画布的尺寸(单位:像素px)
const width = window.innerWidth; //宽度
const height = window.innerHeight; //高度
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
// renderer.setPixelRatio(window.devicePixelRatio)
renderer.render(scene, camera); //执行渲染操作const controls = new MapControls(camera, renderer.domElement);
controls.enablePan = false; //禁止右键拖拽
controls.enableZoom = false;//禁止缩放
controls.addEventListener('change', function () {// 鼠标右键旋转时候,查看.position变化// 鼠标左键拖动的时候,查看.position、.target的位置会变化console.log('camera.position', camera.position);renderer.render(scene, camera); //执行渲染操作// console.log('controls.target', controls.target);
});// --------- UI界面 ---------------
// 实例化一个gui对象
const gui = new GUI();// gui增加交互界面,用来改变obj对应属性
gui.add(mesh.position, 'x', 0, 15);
gui.add(mesh.position, 'y', 0, 15);
gui.add(mesh.position, 'z', 0, 15);function render() {// i+=1;// console.log('执行次数'+i);renderer.render(scene, camera); //执行渲染操作requestAnimationFrame(render);//请求再次执行函数render
}
render();
// ----------渲染器添加到页面------------
// 一定要放在onmounted里面,因为在onmounted的时候才有webgl这个dom元素
onMounted(() => {console.log('mounted');webgl.value.appendChild(renderer.domElement);// 监听浏览器窗口大小的变化,变化时重新渲染window.addEventListener('resize', () => {const width = window.innerWidth; //宽度const height = window.innerHeight; //高度// camera.position.set(20, 20, 20);camera.lookAt(mesh.position);//指向mesh对应的位置// 更新相机的宽高比camera.aspect = width / height;// 更新摄像机的投影矩阵camera.updateProjectionMatrix();renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)renderer.render(scene, camera); //执行渲染操作});})</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#webgl {width: 100px;height: 100px;
}
</style>

threeFun.js

import * as THREE from "three";
/**** @param {*} scene* @param {*} type 几何体类型* @param {*} size 几何体参数* @param {*} pos 放置位置数组* @param {*} material 材质对象*/
export function createGeometry(scene, type, size, pos, material) {console.log(scene, type, size, pos, material);let mesh;switch (type) {case "Box":mesh = createBox(scene, size, pos, material);break;case "Sphere":mesh = createSphere(scene, size, pos, material);break;case "Cylinder":mesh = createCylinder(scene, size, pos, material);break;case "Plane":mesh = createPlane(scene, size, pos, material);break;case "Circle":mesh = createCircle(scene, size, pos, material);break;default:console.log("类型错误");}return mesh;
}// ----------示例代码---------
// //创建一个长方体几何对象Geometry
// const geometry = new THREE.BoxGeometry(100, 100, 100);
// //创建一个材质对象Material
// const material = new THREE.MeshBasicMaterial({
//   color: 0xff0000,//0xff0000设置材质颜色为红色
// });
// // 两个参数分别为几何体geometry、材质material
// const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
// //设置网格模型在三维空间中的位置坐标,默认是坐标原点
// let pos = [0, 10, 0]
// mesh.position.set(...pos);
// scene.add(mesh); //网格模型添加到场景中function createBox(scene, size, pos, materialParams) {const geometry = new THREE.BoxGeometry(...size);//   const geometry = new THREE.BoxGeometry(100, 100, 100);//创建一个材质对象Materialconst material = new THREE.MeshBasicMaterial(materialParams);const mesh = new THREE.Mesh(geometry, material); //网格模型对象Meshmesh.position.set(...pos);scene.add(mesh);console.log(scene);return mesh;
}
function createSphere(scene, size, pos, materialParams) {const geometry = new THREE.SphereGeometry(...size);//创建一个材质对象Materialconst material = new THREE.MeshBasicMaterial(materialParams);const mesh = new THREE.Mesh(geometry, material); //网格模型对象Meshmesh.position.set(...pos);scene.add(mesh);return mesh;
}
function createCylinder(scene, size, pos, materialParams) {const geometry = new THREE.CylinderGeometry(...size);//创建一个材质对象Materialconst material = new THREE.MeshBasicMaterial(materialParams);const mesh = new THREE.Mesh(geometry, material); //网格模型对象Meshmesh.position.set(...pos);scene.add(mesh);return mesh;
}
function createPlane(scene, size, pos, materialParams) {const geometry = new THREE.PlaneGeometry(...size);//创建一个材质对象Materialconst material = new THREE.MeshBasicMaterial(materialParams);const mesh = new THREE.Mesh(geometry, material); //网格模型对象Meshmesh.position.set(...pos);scene.add(mesh);return mesh;
}
function createCircle(scene, size, pos, materialParams) {const geometry = new THREE.CircleGeometry(...size);//创建一个材质对象Materialconst material = new THREE.MeshBasicMaterial(materialParams);const mesh = new THREE.Mesh(geometry, material); //网格模型对象Meshmesh.position.set(...pos);scene.add(mesh);return mesh;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/317438.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Modbus转Profinet解决方案,轻松搭建工业通信“桥梁”

在工业自动化领域&#xff0c;Modbus和Profinet是两种常见的通信协议。由于许多现有的工业设备使用的是Modbus协议&#xff0c;而现代化的工业系统通常采用Profinet&#xff0c;所以将Modbus转换为Profinet成为了解决方案的一个重要需求。 Modbus转Profinet解决方案具体包括以下…

Minio集群部署(docker版本)

先在/etc/hosts中添加虚拟域名 {ip} minio1 {ip} minio2 执行docker命令 docker run -it -d --name minio-01 --restartalways --nethost \ -e "MINIO_ROOT_USER{用户名}" \ -e "MINIO_ROOT_PASSWORD{密码}" \ -v /data/docker/minio/update:/data1 #…

CMake入门教程【基础篇】CMake+Visual Studio2022构建C++项目

文章目录 1.概述2.Visual Studio 2022简介3.安装Visual Studio 20224.安装CMake5.创建CMake项目6. 构建项目 1.概述 CMake和Visual Studio 2022结合 在现代软件开发中&#xff0c;CMake和Visual Studio 2022的结合提供了一个强大的环境&#xff0c;用于构建和管理各种规模的C项…

ITSS服务工程师vs ITSS服务经理:哪个职位更适合你?

✨在信息技术服务领域&#xff0c;ITSS服务工程师和ITSS服务经理是两个极具吸引力的职位。但它们各自的特点和要求是什么&#xff1f;哪个更适合你的职业规划和个人兴趣&#xff1f;接下来&#xff0c;我们将为你详细解读这两个职位的区别&#xff0c;帮助你做出明智的选择&…

环境准备-VMware安装

照顾到很多人不是很会环境搭建,我这里会将搭建的步骤讲的细致点 第一步,VMware下载。目的是通过VMware搭建Linux服务器,因为大家大部分还是Windows的电脑,我们先下载虚拟机搭建一个Linux系统的服务器 下载完成之后,点击安装,如下: 点击“下一步” 勾选“我接受许可协议…

【解决|三方工具】导入 XChart 后提示丢失关于 TMPPro 工具引用

开发平台&#xff1a;Unity 2021 版本 插件版本&#xff1a;XChart 3.0&#xff1a;官方文档 - https://github.com/XCharts-Team/XCharts   问题描述 导入 XChart 插件至 Unity 中出现 目录&#xff1a;Component、Theme 等提示丢失 TMPPro&#xff08;TextMeshPro 工具&…

【数据结构和算法】寻找数组的中心下标

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 前缀和的解题模板 2.1.1 最长递增子序列长度 2.1.2 寻找数组中第 k 大的元素 2.1.3 最长公共子序列…

什么是Maven ??? (以及关于依赖,中央仓库,国内源)

文章目录 什么是 Maven创建第一个 Maven 项目依赖管理Maven 的仓库Maven 如何设置国内源 什么是 Maven Maven &#xff1a;用于构建和管理任何基于java的项目的工具。**说白了就是管理 Java项目 的工具。**我们希望我们已经创建了一些东西&#xff0c;可以使Java开发人员的日常…

paddle v4 hubserving 部署

环境准备&#xff1a;https://github.com/PaddlePaddle/PaddleOCR/tree/release/2.7/deploy/hubserving#24-%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1 服务器启动命令 hub serving start -c deploy/hubserving/ocr_system/config.json客户端请求 python tools/test_hubserving.…

ImportError: cannot import name ‘is_npu_available‘ from ‘accelerate.utils

在做LoRa微调使用peft库的时候出现了下面的错误&#xff0c; ImportError: cannot import name is_npu_available from accelerate.utils 解决方法&#xff1a; pip uninstall peft pip install peftgithttps://github.com/huggingface/peft.git

知识库:提升客服效率的利器

相信大家都有过这样的经历&#xff1a;在需要帮助或解决问题时&#xff0c;与客服沟通却遇到了冗长的等待时间、低效的回答和重复的解决方案。这些问题不仅令人沮丧&#xff0c;也给企业带来了巨大的挑战。然而&#xff0c;随着技术的发展&#xff0c;客服系统中的知识库正逐渐…

tp8/6 插件PhpOffice\PhpSpreadsheet导入表格

一、安装 composer require phpoffice/phpspreadsheet 官网&#xff1a;phpoffice/phpspreadsheet - Packagist 二、代码 <?php namespace app\services\upload\model; use app\services\BaseServices; use \PhpOffice\PhpSpreadsheet\Spreadsheet; use \PhpOffice\Php…