Vue3+Three.js星空球体
2024-01-03 02:37:07
结果图
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 // 双面展示
}
)
记得天空盒是需要双面贴图的,因为视角在里面,不然是看不见贴图的
具体代码
<template>
<div ref="webgl"></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';
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);
});
// ----------渲染器添加到页面------------
// 一定要放在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);
//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial(materialParams);
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
mesh.position.set(...pos);
scene.add(mesh);
console.log(scene);
return mesh;
}
function createSphere(scene, size, pos, materialParams) {
const geometry = new THREE.SphereGeometry(...size);
//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial(materialParams);
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
mesh.position.set(...pos);
scene.add(mesh);
return mesh;
}
function createCylinder(scene, size, pos, materialParams) {
const geometry = new THREE.CylinderGeometry(...size);
//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial(materialParams);
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
mesh.position.set(...pos);
scene.add(mesh);
return mesh;
}
function createPlane(scene, size, pos, materialParams) {
const geometry = new THREE.PlaneGeometry(...size);
//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial(materialParams);
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
mesh.position.set(...pos);
scene.add(mesh);
return mesh;
}
function createCircle(scene, size, pos, materialParams) {
const geometry = new THREE.CircleGeometry(...size);
//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial(materialParams);
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
mesh.position.set(...pos);
scene.add(mesh);
return mesh;
}
文章来源:https://blog.csdn.net/ArmadaDK/article/details/135345320
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!