推荐3D模型库: sketchfab.com

大量免费模型可供下载

天空盒分享: 天空盒素材

加载gltf模型首先需要引入Three.js内置GLTF加载器

import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"

然后实例化加载器, 引入模型地址, 最后添加到场景中

注意: gltf模型存放在assets文件夹中, 必须是完整的gltf文件, 如下:

//添加模型
    const loader = new GLTFLoader()
    loader.load("src/assets/tudao/scene.gltf", (gltf) => {
        gltf.scene.position.set(-2.2, -0.5 , 0.8)   // 模型位置
        gltf.scene.rotation.y = Math.PI / 2     // y轴旋转
        gltf.scene.rotation.z = -Math.PI / 8    // z轴旋转
        scene.add(gltf.scene)   // 加入场景
    })

加载天空盒(可选)

three.js中天空盒加载顺序为: right, left, top, down, back, front (右, 左, 上, 下, 后, 前)

 // 创建天空盒
    // 相应面对应相应图片
    const imgUrl = [
        'src/assets/bak5/right.jpg',
        'src/assets/bak5/left.jpg',
        'src/assets/bak5/top.jpg',
        'src/assets/bak5/down.jpg',
        'src/assets/bak5/back.jpg',
        'src/assets/bak5/front.jpg',
    ]
    // 调用getTexturesFromAtlasFile() 给每个材质加上相应的图片
    const textures = getTexturesFromAtlasFile(imgUrl, 6)
    const materials = []

    for (let i = 0; i < 6; i++) {
        // 创造六个面的材质
        materials.push(new THREE.MeshBasicMaterial({ map: textures[i] }))
    }
    //创造包围盒
    const skyBox = new THREE.Mesh(new THREE.BoxBufferGeometry(1024, 1024, 1024), materials)
    // skyBox.position.set(0, 0, 0);
    skyBox.geometry.scale(1, 1, -1)
    scene.add(skyBox)
    // 六个面添加图片
    function getTexturesFromAtlasFile (atlasImgUrl, tilesNum) {
        const textures = []

        for (let i = 0; i < tilesNum; i++) {
            textures[i] = new THREE.Texture()
        }

        for (let i = 0; i < textures.length; i++) {
            const imageObj = new Image()
            imageObj.src = atlasImgUrl[i]
            imageObj.onload = () => {
                let context = ''
                // let tileWidth = imageObj.height;
                // let tileWidth = 5000;

                const canvas = document.createElement('canvas')
                // const canvas: HTMLCanvasElement = this.canvasRef.nativeElement;  // 得到canvas 元素
                context = canvas.getContext('2d')
                const canvasHeight = 720
                canvas.height = canvasHeight
                canvas.width = canvasHeight
                // context.drawImage( imageObj, canvasHeight * i, 0, canvasHeight, canvasHeight, 0, 0, canvasHeight, canvasHeight );
                context.drawImage(imageObj, 0, 0, canvasHeight, canvasHeight)
                textures[i].image = canvas
                textures[i].needsUpdate = true
            }
        }
        return textures
    }

全部代码

<template>
    <div class="canvas-container" ref="screenDom"></div>
</template>

<script setup>
import * as THREE from 'three'
import { ref, onMounted } from "vue"
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"
let screenDom = ref(null)

onMounted(() => {
    //创建场景
    let scene = new THREE.Scene()
    //创建相机
    let camera = new THREE.PerspectiveCamera(
        100,
        screenDom.value.clientWidth / screenDom.value.clientHeight,
        0.1,
        1000
    );
    camera.position.set(0, 1, 5);

    //创建渲染器
    let renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(screenDom.value.clientWidth, screenDom.value.clientHeight);
    screenDom.value.appendChild(renderer.domElement)

    //添加控制器
    let control = new OrbitControls(camera, renderer.domElement)

    // 创建天空盒
    // 相应面对应相应图片
    const imgUrl = [
        'src/assets/bak5/right.jpg',
        'src/assets/bak5/left.jpg',
        'src/assets/bak5/top.jpg',
        'src/assets/bak5/down.jpg',
        'src/assets/bak5/back.jpg',
        'src/assets/bak5/front.jpg',
    ]
    // 调用getTexturesFromAtlasFile() 给每个材质加上相应的图片
    const textures = getTexturesFromAtlasFile(imgUrl, 6)
    const materials = []

    for (let i = 0; i < 6; i++) {
        // 创造六个面的材质
        materials.push(new THREE.MeshBasicMaterial({ map: textures[i] }))
    }
    //创造包围盒
    const skyBox = new THREE.Mesh(new THREE.BoxBufferGeometry(1024, 1024, 1024), materials)
    // skyBox.position.set(0, 0, 0);
    skyBox.geometry.scale(1, 1, -1)
    scene.add(skyBox)
    // 六个面添加图片
    function getTexturesFromAtlasFile (atlasImgUrl, tilesNum) {
        const textures = []

        for (let i = 0; i < tilesNum; i++) {
            textures[i] = new THREE.Texture()
        }

        for (let i = 0; i < textures.length; i++) {
            const imageObj = new Image()
            imageObj.src = atlasImgUrl[i]
            imageObj.onload = () => {
                let context = ''
                // let tileWidth = imageObj.height;
                // let tileWidth = 5000;

                const canvas = document.createElement('canvas')
                // const canvas: HTMLCanvasElement = this.canvasRef.nativeElement;  // 得到canvas 元素
                context = canvas.getContext('2d')
                const canvasHeight = 720
                canvas.height = canvasHeight
                canvas.width = canvasHeight
                // context.drawImage( imageObj, canvasHeight * i, 0, canvasHeight, canvasHeight, 0, 0, canvasHeight, canvasHeight );
                context.drawImage(imageObj, 0, 0, canvasHeight, canvasHeight)
                textures[i].image = canvas
                textures[i].needsUpdate = true
            }
        }
        return textures
    }

    //添加模型
    const loader = new GLTFLoader()
    loader.load("src/assets/tudao/scene.gltf", (gltf) => {
        gltf.scene.position.set(-2.2, -0.5 , 0.8)   // 模型位置
        gltf.scene.rotation.y = Math.PI / 2     // y轴旋转
        gltf.scene.rotation.z = -Math.PI / 8    // z轴旋转
        scene.add(gltf.scene)   // 加入场景
    })
    loader.load("src/assets/csgo_terrorist_characters/scene.gltf", (gltf) => {
        gltf.scene.scale.set(0.1, 0.1, 0.1);
        gltf.scene.position.set(0, -4, 0)
        scene.add(gltf.scene)
    })
    loader.load("src/assets/tudao/scene.gltf", (gltf) => {
        gltf.scene.position.set(2.15, -0.5, 0.8)
        gltf.scene.rotation.y = Math.PI / 2
        gltf.scene.rotation.z = -Math.PI / 8
        scene.add(gltf.scene)
    })
    
    //添加直线光
    let light1 = new THREE.DirectionalLight(0xffffff, 1)
    light1.position.set(0, 50, 50)
    let light2 = new THREE.DirectionalLight(0xffffff, 1)
    light2.position.set(0, 50, -50)
    let light3 = new THREE.DirectionalLight(0xffffff, 1)
    light3.position.set(50, 50, 50)
    let light4 = new THREE.DirectionalLight(0xffffff, 1)
    light4.position.set(-50, -10, 0)
    let light5 = new THREE.DirectionalLight(0xffffff, 1)
    light5.position.set(0, 0, 50)
    let light6 = new THREE.DirectionalLight(0xffffff, 1)
    light6.position.set(0, 0, -50)
    let light7 = new THREE.DirectionalLight(0xffffff, 1)
    light7.position.set(50, 0, 0)
    let light8 = new THREE.DirectionalLight(0xffffff, 1)
    light8.position.set(-50, 0, 0)
    scene.add(light1, light2, light3, light4, light5, light6, light7, light8)

    //绘制画布
    function render () {
        requestAnimationFrame(render);
        renderer.render(scene, camera)
    }
    render()
})

</script>

<style lang="scss" scoped>
.canvas-container {
    width: 100%;
    height: 100%;
}
</style>

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐