vue3+ts 展示fbx与tga贴图
npm i three --save
<template>
<div ref="modelContainer"></div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import * as THREE from 'three';
import { FBXLoader } from 'three/addons/loaders/FBXLoader'; // 导入FBXLoader
import { TGALoader } from 'three/examples/jsm/loaders/TGALoader'
const modelContainer = ref<HTMLElement | null>(null);
let fbxModel = null as any;
onMounted(() => {
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 2.5;
camera.position.y = 1.5;
// 设置alpha为true
// 设置clearColor为透明
// 创建渲染器
const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000, 0);
modelContainer.value?.appendChild(renderer.domElement);
// 创建FBX加载器
const loader = new FBXLoader();
const tgaloader = new TGALoader()
// 贴图路径数组
const texturePaths = [
'/public/models/LoGo_D.tga',
'/public/models/LoGo_N.tga'
];
// 加载FBX模型
loader.load(
'/public/models/LoGo.fbx',
(fbx) => {
fbxModel = fbx;
// 创建一个包含多个贴图的数组
const textures = texturePaths.map(path => {
const texture = tgaloader.load(path);
texture.colorSpace = THREE.SRGBColorSpace;
return texture;
});
// 创建一个包含多个贴图的uniform对象
const uniforms = {
texture1: { value: textures[0] },
texture2: { value: textures[1] },
};
// 顶点着色器代码
const vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
// 片段着色器代码
const fragmentShader = `
varying vec2 vUv;
uniform sampler2D texture1;
uniform sampler2D texture2;
void main() {
vec4 color1 = texture2D(texture1, vUv);
vec4 color2 = texture2D(texture2, vUv);
gl_FragColor = mix(color1, color2, 0.001);
}
`;
// 创建着色器材质
const material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vertexShader,
fragmentShader: fragmentShader,
});
// 遍历模型的所有子网格
fbx.traverse((child: any) => {
if (child instanceof THREE.Mesh) {
// 应用着色器材质到子网格
child.material = material;
}
});
scene.add(fbxModel);
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded');
},
(error) => {
console.error(error);
}
);
// 创建光源
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1);
camera.add(pointLight);
scene.add(camera);
// 渲染场景
const animate = () => {
requestAnimationFrame(animate);
// 根据滚动条位置调整模型的旋转角度
if (fbxModel) {
fbxModel.rotation.y += 0.01;
}
// const scrollTops = window.pageYOffset || document.documentElement.scrollTop;
// if (scrollTops >= 12220) {
// const maxRotation = Math.PI / 2; // 最大旋转角度为90度,模型躺下
// fbxModel.rotation.y = maxRotation * scrollTops;
// }
// 在这里可以添加模型的旋转或其他动画
renderer.render(scene, camera);
};
animate();
});
</script>
<style scoped>
/* 在这里可以添加样式 */
</style>
iframe子页面与父页面
<script>
//子页面 iframe
window.parent.postMessage({data:'data'}, '*');
//父页面
window.addEventListener('message',
function (e: any) {
if (e.data.action === "closeLoading") {
TransferMethod()
}
},
false
)
</script>
本文含有隐藏内容,请 开通VIP 后查看