没有二十年功力,写不出这一行“看似无用”的代码

素材:

链接: https://pan.baidu.com/s/1HbT0SlFHwfQbrKH9tXlM5w

提取码: e98i

新引入:

    import {
        RGBELoader
    } from "three/examples/jsm/loaders/RGBELoader"
    import {
        Water
    } from "three/examples/jsm/objects/Water2";
    import {
        GLTFLoader
    } from "three/examples/jsm/loaders/GLTFLoader"
    import {
        DRACOLoader
    } from "three/examples/jsm/loaders/DRACOLoader"

关键代码:

片段1

            const regbeLoader = new RGBELoader();
            regbeLoader.loadAsync('three/050.hdr').then(loader => {
                loader.mapping = THREE.EquirectangularReflectionMapping;
                scene.background = loader;
                scene.environment = loader;
            })

片段2 

 let cloudLoader = new THREE.TextureLoader();
            cloudLoader = cloudLoader.load('three/textures/sky.jpg');
            const cloudMaterial = new THREE.MeshBasicMaterial({
                map: cloudLoader
            });
            const mesh = new THREE.Mesh(boxBufferGeometry, cloudMaterial);
            mesh.geometry.scale(1, -1, 1);
            //将物体加入到场景
            scene.add(mesh);

片段3 

//创建水面
            //创建圆
            const circleGeometry = new THREE.CircleBufferGeometry(400, 100);
            // circleGeometry.rotation.x =-Math.PI/2;
            const textureLoader = new THREE.TextureLoader();
            const waterMesh = new Water(circleGeometry, {
                textureWidth: 1024,
                textureHeight: 1024,
                color: 0xeeeeff,
                flowDirection: new THREE.Vector2(1, 1),
                scale: 1,
                flowMap:textureLoader.load("three/textures/water/Water_1_M_Flow.jpg"),
                normalMap1: textureLoader.load("three/textures/water/Water_1_M_Normal.jpg"),
                normalMap2: textureLoader.load("three/textures/water/Water_2_M_Normal.jpg"),
            });
            waterMesh.rotation.x = -Math.PI / 2;
            scene.add(waterMesh);

片段4 

             //加载模型
            const loader = new GLTFLoader().setPath('three/glb/');
            const dracoLoader = new DRACOLoader();
            dracoLoader.setDecoderPath('three/draco/')
            // dracoLoader.setDecoderConfig({
            //     type: 'js'
            // })
            dracoLoader.preload();
            loader.setDRACOLoader(dracoLoader);
            loader.load('island.glb', gltf => {
                scene.add(gltf.scene);
            })
            const videoELem = document.createElement("video");
            videoELem.src = "three/textures/sky.mp4";
            videoELem.loop = true;
            //创建视频纹理
            window.addEventListener("click", () => {
                if(videoELem.paused){
                    videoELem.play();
                    cloudMaterial.map = new THREE.VideoTexture(videoELem);
                    cloudMaterial.map.needsUpdate = true;
                    //scene.background = textureLoader
                }
            })

片段5 

    /*设置场景渲染编码threejs将贴图的编码都默认设置为THREE.LinearEncoding,
     *导致图片色彩失真(色彩不像正常那么鲜艳,会灰蒙蒙的),所以务必将场景中的所有贴图的编码都调整为THREE.sRGBEncoding
     */
    render.outputEncoding =THREE.sRGBEncoding; 

完整代码:

<template>
    <div id="three_div"></div>
</template>

<script>
    import * as THREE from "three";
    import {
        OrbitControls
    } from "three/examples/jsm/controls/OrbitControls";
    import {
        RGBELoader
    } from "three/examples/jsm/loaders/RGBELoader"
    import {
        Water
    } from "three/examples/jsm/objects/Water2";
    import {
        GLTFLoader
    } from "three/examples/jsm/loaders/GLTFLoader"
    import {
        DRACOLoader
    } from "three/examples/jsm/loaders/DRACOLoader"
    export default {
        name: "HOME",
        components: {
            // vueQr,
            // glHome,
        },
        data() {
            return {};
        },
        mounted() {
            //使用控制器控制3D拖动旋转OrbitControls
            //控制3D物体移动

            //1.创建场景
            const scene = new THREE.Scene();
            console.log(scene);

            //2.创建相机
            const camera = new THREE.PerspectiveCamera(
                75,
                window.innerWidth / window.innerHeight,
                0.1,
                20000
            );
            //设置相机位置
            camera.position.set(0, 0, 10);
            //将相机添加到场景
            scene.add(camera);
            //添加物体
            //创建一个半径为1,经纬度分段数位20的球
            const boxBufferGeometry = new THREE.SphereBufferGeometry(500, 50, 50);
            //纹理加载器
            const regbeLoader = new RGBELoader();
            regbeLoader.loadAsync('three/050.hdr').then(loader => {
                loader.mapping = THREE.EquirectangularReflectionMapping;
                scene.background = loader;
                scene.environment = loader;
            })
            let cloudLoader = new THREE.TextureLoader();
            cloudLoader = cloudLoader.load('three/textures/sky.jpg');
            const cloudMaterial = new THREE.MeshBasicMaterial({
                map: cloudLoader
            });
            const mesh = new THREE.Mesh(boxBufferGeometry, cloudMaterial);
            mesh.geometry.scale(1, -1, 1);
            //将物体加入到场景
            scene.add(mesh);
            //创建水面
            //创建圆
            const circleGeometry = new THREE.CircleBufferGeometry(400, 100);
            // circleGeometry.rotation.x =-Math.PI/2;
            const textureLoader = new THREE.TextureLoader();
            const waterMesh = new Water(circleGeometry, {
                textureWidth: 1024,
                textureHeight: 1024,
                color: 0xeeeeff,
                flowDirection: new THREE.Vector2(1, 1),
                scale: 1,
                flowMap:textureLoader.load("three/textures/water/Water_1_M_Flow.jpg"),
                normalMap1: textureLoader.load("three/textures/water/Water_1_M_Normal.jpg"),
                normalMap2: textureLoader.load("three/textures/water/Water_2_M_Normal.jpg"),
            });
            waterMesh.rotation.x = -Math.PI / 2;
            scene.add(waterMesh);
            //给场景所有的物体添加默认的环境贴图
            //添加坐标轴辅助器
            // const axesHepler = new THREE.AxesHelper(5);
            // scene.add(axesHepler);
            //添加周围环境灯光(由物体发出的灯光)参数(灯色,强度0-1)
            const light = new THREE.AmbientLight(0xFFFFFF, 1);
            scene.add(light);
            //加载模型
            const loader = new GLTFLoader().setPath('three/glb/');
            const dracoLoader = new DRACOLoader();
            dracoLoader.setDecoderPath('three/draco/')
            // dracoLoader.setDecoderConfig({
            //     type: 'js'
            // })
            dracoLoader.preload();
            loader.setDRACOLoader(dracoLoader);
            loader.load('island.glb', gltf => {
                scene.add(gltf.scene);
            })
            const videoELem = document.createElement("video");
            videoELem.src = "three/textures/sky.mp4";
            videoELem.loop = true;
            //创建视频纹理
            window.addEventListener("click", () => {
                if(videoELem.paused){
                    videoELem.play();
                    cloudMaterial.map = new THREE.VideoTexture(videoELem);
                    cloudMaterial.map.needsUpdate = true;
                    //scene.background = textureLoader
                }
            })
            
            
            
            //初始化渲染器
            const render = new THREE.WebGLRenderer();
            /*设置场景渲染编码threejs将贴图的编码都默认设置为THREE.LinearEncoding,
             *导致图片色彩失真(色彩不像正常那么鲜艳,会灰蒙蒙的),所以务必将场景中的所有贴图的编码都调整为THREE.sRGBEncoding
             */
            render.outputEncoding = THREE.sRGBEncoding;
            //设置渲染器的尺寸
            render.setSize(window.innerWidth, window.innerHeight);
            //使用渲染器,通过相机将场景渲染进来

            //创建轨道控制器,可以拖动,控制的是摄像头
            const controls = new OrbitControls(camera, render.domElement);
            //设置控制阻尼,让控制器有更真实的效果
            controls.enableDamping = true;

            //将webgl渲染的canvas内容添加到body上
            document.getElementById("three_div").appendChild(render.domElement);

            //渲染下一帧的时候就会调用回调函数
            let renderFun = () => {
                //更新阻尼数据
                controls.update();
                //需要重新绘制canvas画布
                render.render(scene, camera);
                //监听屏幕刷新(60HZ,120HZ),每次刷新触发一次requestAnimationFrame回调函数
                //但是requestAnimationFrame的回调函数注册生命只有一次,因此需要循环注册,才能达到一直调用的效果
                window.requestAnimationFrame(renderFun);
            };
            // window.requestAnimationFrame(renderFun);
            renderFun();

            //画布全屏
            window.addEventListener("dblclick", () => {
                if (document.fullscreenElement) {
                    document.exitFullscreen();
                } else {
                    //document.documentElement.requestFullscreen();
                    render.domElement.requestFullscreen();
                }
            });

            //监听画面变化,更新渲染画面,(自适应的大小)
            window.addEventListener("resize", () => {
                //更新摄像机的宽高比
                camera.aspect = window.innerWidth / window.innerHeight;
                //更新摄像机的投影矩阵
                camera.updateProjectionMatrix();
                //更新渲染器宽度和高度
                render.setSize(window.innerWidth, window.innerHeight);
                //设置渲染器的像素比
                render.setPixelRatio(window.devicePixelRatio);
                console.log("画面变化了");
            });
            
        },
        methods: {
            paush(animate) {
                animate.pause();
            },
        },
    };
</script>

<style scoped lang="scss">
</style>

效果图: 

猜你喜欢

转载自blog.csdn.net/AS011x/article/details/127225081