【3D商城】三维场景搭建与开发流程

创建一个场景组件

在这里插入图片描述
在views中创建一个场景组件Scene.vue并且在router的index.js中,通过路由映射到场景组件

const routes = [
{
    path: "/scene",
    component: () => import("../views/Scene.vue"),
    name: "scene",
  },
]

安装 threejs

打开终端,输入

npm i three --save

创建Base3d.js

在目录下创建utils文件夹并且在文件夹下创建文件Base3d.js,在Scene.vue里面导入Base3d.js,如下:

import Base3d from "../utils/Base3d.js";

渲染整个canvas画布,三维的效果立体的事件

<template>
  <div class="scene" id="scene"></div>
</template>

<script setup>
import Base3d from "../utils/Base3d.js";
import { reactive, onMounted } from "vue";
const data = reactive({
  base3d: {},
});

onMounted(() => {
  data.base3d = new Base3d("#scene");
});
</script>

然后在Base3d.js中首先导入threejs

import * as THREE from "three";

导入RGBELoader

import { RGBELoader } from  "three/examples/jsm/loaders/RGBELoader";

初始化场景

在Base3d{}中构建一个constructor(),首先传入一个选择器selector,这个选择器代表我们要去找到一个对象。找到之后把整个画布渲染到对象当中,同时,需要一个摄像头对象(camera)。之所以看到的东西会动,其实物品没有动,只是摄像头在移动,所以看上去才会动,同时需要一个场景(scene),当摄像头和场景真正需要显示画面还需要一个render对象。构建需要初始化init,初始化需要把相机初始化出来,场景初始化出来。

class Base3d {
  constructor(selector, onFinish) {
    this.container = document.querySelector(selector);
    this.camera;
    this.scene;
    this.renderer;
    this.init();
    this.animate();
	}
	init() {
    //   初始化场景
    this.initScene();
    // 初始化相机
    this.initCamera();

    // 初始化渲染器
    this.initRenderer();
    }
	initScene() {
    this.scene = new THREE.Scene();    //构建出一个场景
    this.setEnvMap("000");
  }
}

初始化相机

在构建相机对象的时候,用透视相机PerspectiveCamera,因为有透视的视角才能看到三维立体的效果,视角通常为45度(屏幕上看上去更加真实),设置浏览器显示的宽高比例来设置相机(window.innerWidth / window.innerHeight),设置最近的距离0.25,最远距离200,设置相机的三维的位置,比如(-1.8,0.6,2.7)

  initCamera() {
    this.camera = new THREE.PerspectiveCamera(   //透视相机
      45,
      window.innerWidth / window.innerHeight,
      0.25,
      200
    );
    this.camera.position.set(-1.8, 0.6, 2.7);
  }

初始化渲染器

把画面显示出来需要初始化渲染器,为了更高清一点,避免锯齿使用抗锯齿(antialias),设置屏幕像素比(window.devicePixelRatio),渲染的尺寸大小(window.innerWidth, window.innerHeight)然后进行一个追加,把渲染器渲染的画面,放到选择器上.container.appendChild(this.renderer.domElement) 把渲染器渲染的元素放进来

  initRenderer() {
    this.renderer = new THREE.WebGLRenderer({ antialias: true });
    // 设置屏幕像素比
    this.renderer.setPixelRatio(window.devicePixelRatio);
    // 渲染的尺寸大小
    this.renderer.setSize(window.innerWidth, window.innerHeight);
    this.container.appendChild(this.renderer.domElement);
  }

添加环境的纹理

用加载器来加载HDR

  setEnvMap(hdr) {
    new RGBELoader().setPath("./files/hdr/").load(hdr + ".hdr", (texture) => {
      this.scene.background = texture;
      this.scene.environment = texture;
    });
  }

现在渲染器已经初始化了但是还没有渲染,需要再写一个渲染函数render(),把摄像头和动画渲染进来,由于页面是不断刷新的需要一帧一帧画出来一帧一帧画出来我们可以做一个请求动画帧,就是不断地去渲染,不断地画出来。只要数据一变就可以画出新的内容,这样就可以形成一个动画,然后通过setAnimationLoop这个循环,进行对render绑定,一帧画完,画下一帧

  render() {
    this.renderer.render(this.scene, this.camera);
  }
    animate() {
    this.renderer.setAnimationLoop(this.render.bind(this));
  }

运行后显示效果如下
在这里插入图片描述
但是现在只是一张图没有显示在圆球里面,因此在纹理加载完成后我们需要进行设置纹理的一个映射:
texture.mapping = THREE.EquirectangularReflectionMapping;

  setEnvMap(hdr) {
    new RGBELoader().setPath("./files/hdr/").load(hdr + ".hdr", (texture) => {
      texture.mapping = THREE.EquirectangularReflectionMapping;
      this.scene.background = texture;
      this.scene.environment = texture;
    });
  }

这么设置后画面会改过来:
在这里插入图片描述
内容正常,但是因为这是一个场景,摄像头看后面的内容是会比较模糊的,并不是因为图不够高清,而是因为摄像头聚焦中间,后面的背景会进行虚化,所以会模糊。

  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值