THREE.JS实现看房自由(VR看房)

news2024/11/18 15:22:58

在这里插入图片描述


VR看房

    • 一、前言
    • 二、基础知识
    • 三、场景
      • 3.1 网络模型
      • 3.2 光照
        • 3.2.1 环境光
        • 3.2.2 平行光
        • 3.2.3 点光源
        • 3.2.4 聚光灯
        • 3.2.5 半球光
    • 四、相机
      • 4.1 正交相机
      • 4.2 透视相机
    • 五、渲染器
    • 六、贴图纹理
      • 6.1 基础介绍
      • 6.2 环境贴图
      • 6.3 HDR处理
    • 七、拓展
      • 7.1 坐标系
      • 7.2 控制器
      • 7.3 自适应
      • 7.4 全屏响应
      • 7.5 信息面板
      • 7.6 频率检测
      • 7.7 导航网格
    • 八、源码


一、前言

概述:基于WebGL的三维引擎,目前是国内资料最多、使用最广泛的三维引擎,可以制作一些3D可视化项目

在这里插入图片描述

目前随着元宇宙概念的爆火,THREE技术已经深入到了物联网、VR、游戏、数据可视化等多个平台,今天我们主要基于THREE实现一个三维的VR看房小项目

二、基础知识

在这里插入图片描述

Three.js一般分为三个部分:场景相机渲染器,这三个主要的分支就构成了THREE.JS的主要功能区,这三大部分还有许多细小的分支,这些留到我们后续抽出一些章节专门讲解一下。

在这里插入图片描述

工作流程场景——相机——渲染器

实际生活中拍照角度立方体网格模型和光照组成了一个虚拟的三维场景,相机对象就像你生活中使用的相机一样可以拍照,只不过一个是拍摄真实的景物,一个是拍摄虚拟的景物。拍摄一个物体的时候相机的位置和角度需要设置,虚拟的相机还需要设置投影方式,当你创建好一个三维场景,相机也设置好,就差一个动作“咔”,通过渲染器就可以执行拍照动作。

三、场景

概述:场景主要由网络模型与光照组成,网络模型分为几何体与材质

3.1 网络模型

几何体就像我们小时候学我们就知道点线面体四种概念,点动成线,线动成面,面动成体,而材质就像是是几何体上面的涂鸦,有不同的颜色、图案…

例子如下

在这里插入图片描述

//打造酷炫三角形
for (let i = 0; i < 50; i++) { 
    const geometry = new THREE.BufferGeometry();
    const arr = new Float32Array(9);
    for (let j = 0; j < 9; j++) { 
        arr[j] = Math.random() * 5;
    }
    geometry.setAttribute('position', new THREE.BufferAttribute(arr, 3));
    let randomColor = new THREE.Color(Math.random(), Math.random(), Math.random());
    const material = new THREE.MeshBasicMaterial({
        color: randomColor,
        transparent: true,
        opacity:0.5,
    });
    const mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UlBSgxKr-1666681292595)(https://gitee.com/riskbaby/picgo/raw/master/blog/202209211037215.png#pic_center)]

const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshStandardMaterial({ color: 0x0000ff });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

在这里插入图片描述

const geometry = new THREE.ConeGeometry(5, 15, 32);//底面半径 高 侧边三角分段
const material = new THREE.MeshStandardMaterial({ color: 0x0000ff });
const clone = new THREE.Mesh(geometry, material);
scene.add(clone);

3.2 光照

3.2.1 环境光

概念:光照对three.js的物体全表面进行光照测试,有可能会发生光照融合

在这里插入图片描述

//环境光
const ambient = new THREE.AmbientLight(0x404040);
scene.add(ambient);

3.2.2 平行光

概念:向特定方向发射的光,太阳光也视作平行的一种,和上面比较,物体变亮了

//平行光  颜色 强度
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(100, 100, 100);//光源位置
directionalLight.target = cube;//光源目标 默认 0 0 0
scene.add(directionalLight);

3.2.3 点光源

概念:由中间向四周发射光、强度比平行光小

在这里插入图片描述

// 颜色 强度 距离 衰退量(默认1)
const pointLight = new THREE.PointLight(0xff0000, 1, 100, 1);
pointLight.position.set(50, 50, 50);
scene.add(pointLight);

3.2.4 聚光灯

概念:家里面的节能灯泡,强度较好

在这里插入图片描述

//聚光灯
const spotLigth = new THREE.PointLight(0xffffff);
spotLigth.position.set(50, 50, 50);
spotLigth.target = cube;
spotLigth.angle = Math.PI / 6;
scene.add(spotLigth);

3.2.5 半球光

概念:光源直接放置于场景之上,光照颜色从天空光线颜色渐变到地面光线颜色

在这里插入图片描述

//半球光
const light = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);//天空 场景 
scene.add(light);

四、相机

4.1 正交相机

在这里插入图片描述

参数(属性)含义
left渲染空间的左边界
right渲染空间的右边界
top渲染空间的上边界
bottom渲染空间的下边界
nearnear属性表示的是从距离相机多远的位置开始渲染,一般情况会设置一个很小的值。 默认值0.1
farfar属性表示的是距离相机多远的位置截止渲染,如果设置的值偏小小,会有部分场景看不到。 默认值1000
let width = window.innerWidth;
let height = window.innerHeight;
const camera = new THREE.OrthographicCamera(width / - 2, width / 2, height / 2, height / - 2, 1, 1000);
scene.add(camera);
camera.position.set(100, 200, 100);

4.2 透视相机

在这里插入图片描述

参数含义默认值
fovfov表示视场,所谓视场就是能够看到的角度范围,人的眼睛大约能够看到180度的视场,视角大小设置要根据具体应用,一般游戏会设置60~90度45
aspectaspect表示渲染窗口的长宽比,如果一个网页上只有一个全屏的canvas画布且画布上只有一个窗口,那么aspect的值就是网页窗口客户区的宽高比window.innerWidth/window.innerHeight
nearnear属性表示的是从距离相机多远的位置开始渲染,一般情况会设置一个很小的值。0.1
farfar属性表示的是距离相机多远的位置截止渲染,如果设置的值偏小,会有部分场景看不到1000
let width = window.innerWidth;
let height = window.innerHeight;
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
camera.position.set(150, 100, 300);
camera.lookAt(scene.position);

五、渲染器

概述:从WEBGL的角度来看,three就是对它的进一步封装,想要进一步了解渲染器这方面的知识点还需要了解一下WEBGL,这里我们就不做过多介绍了。

六、贴图纹理

6.1 基础介绍

概述:这部分对于我们是否能够给别人呈现一个真实的渲染场景来说,很重要,比如下面一个普普通通的正方体,我们只要一加上贴图,立马不一样了。

以前

在这里插入图片描述

之后

在这里插入图片描述

6.2 环境贴图

概述:目前有许许多多的贴图,比如基础、透明、环境、法线、金属、粗糙、置换等等,今天我们呢主要讲解一下环境和一点 HDR处理

THREE的世界里面,坐标抽x、y、z的位置关系图如下所示:

2

红、绿、蓝分别代表x、z、y,我们的贴图就是在px nx py ny pz nz这六个方向防止一张图片,其中p就代表坐标轴的正方向

CubeTextureLoader:加载CubeTexture的一个类。 内部使用ImageLoader来加载文件。

//场景贴图
const sphereTexture = new THREE.CubeTextureLoader().setPath('./textures/course/environmentMaps/0/');
const envTexture= sphereTexture.load([
    'px.jpg',
    'nx.jpg',
    'py.jpg',
    'ny.jpg',
    'pz.jpg',
    'nz.jpg'
]);
//场景添加背景
scene.background = envTexture;
//场景的物体添加环境贴图(无默认情况使用)
scene.environment = envTexture;

const sphereGeometry = new THREE.SphereGeometry(5, 30, 30);
const sphereMaterial = new THREE.MeshStandardMaterial({
    roughness: 0,//设置粗糙程度
    metalness: 1,//金属度
    envMap:envTexture,

});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
scene.add(sphere);

gif图片有点大上传不了,我就截了几张图

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

请添加图片描述

请添加图片描述

6.3 HDR处理

概述:高动态范围图像,相比普通的图像,能够提供更多的动态范围和图像细节,一般被运用于电视显示产品以及图片视频拍摄制作当中。

在这里插入图片描述

import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader;
const rgbeLoader = new RGBELoader().setPath('./textures/course/hdr/');
//异步加载
rgbeLoader.loadAsync('002.hdr').then((texture) => {

    //设置加载方式 等距圆柱投影的环境贴图
    texture.mapping = THREE.EquirectangularReflectionMapping;
    scene.background = texture;
 })

七、拓展

7.1 坐标系

概述:坐标轴能够更好的反馈物体的位置信息,红、绿、蓝分别代表x、z、y

在这里插入图片描述

const axesHelper = new THREE.AxesHelper(20);//里面的数字代表坐标抽长度
scene.add(axesHelper);

7.2 控制器

概述:通过鼠标控制物体和相机的移动、旋转、缩放

导包

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

应用

const controls = new OrbitControls(camera, renderer.domElement)

自旋转

在这里插入图片描述

controls.autoRotate = true

必须在render函数调用update实时更新才奏效

7.3 自适应

概述:根据屏幕大小自适应场景
在这里插入图片描述

//自适应屏幕
window.addEventListener('resize', () => { 
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.setPixelRatio(window.devicePixelRatio)
})

设置相机的宽高比、重新更新渲染相机、渲染器的渲染大小、设备的像素比

7.4 全屏响应

概述:双击进入全屏,再次双击/ESC退出全屏

在这里插入图片描述

window.addEventListener('dblclick', () => { 
    let isFullScreen = document.fullscreenElement
    if (!isFullScreen) {
        renderer.domElement.requestFullscreen()
    }
    else { 
        document.exitFullscreen()
    }
})

7.5 信息面板

概述;通过操作面板完成界面的移动物体的相关应用

链接:https://www.npmjs.com/package/dat.gui

//安装npm
npm install --save dat.gui
//如果出现...标记错误,安装到开发依赖就可以了
npm i --save-dev @types/dat.gui

1

//界面操作
const gui = new dat.GUI();

//操作物体位置
gui
    .add(cube.position, 'x')
    .min(0)
    .max(10)
    .step(0.1)
    .name('X轴移动')
    .onChange((value) => {
        console.log('修改的值为' + value);
    })
    .onFinishChange((value) => {
        console.log('完全停止' + value);
    });
//操作物体颜色
const colors = {
    color: '#0000ff',
};
gui
    .addColor(colors, 'color')
    .onChange((value) => {
        //修改物体颜色
        cube.material.color.set(value);
    });

7.6 频率检测

概述:检测帧率

导包

import Stats from 'three/addons/libs/stats.module.js';

应用

const stats = new Stats();
document.body.appendChild(stats.dom);

自变化

20221021_110002

stats.update()

必须在render函数调用update实时更新才奏效

7.7 导航网格

概述:底部二维平面的网格化,帮助我们更好的创建场景

在这里插入图片描述

const gridHelper = new THREE.GridHelper(10, 20)//网格大小、细分次数
scene.add(gridHelper)

八、源码

//导入包
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import * as dat from 'dat.gui';
import Stats from 'three/addons/libs/stats.module.js';


let scene,camera,renderer

//场景
scene = new THREE.Scene();

//坐标抽
const axesHelper = new THREE.AxesHelper(20);
scene.add(axesHelper);

//场景贴图
const sphereTexture = new THREE.CubeTextureLoader().setPath('./textures/course/environmentMaps/0/');
const envTexture= sphereTexture.load([
    'px.jpg',
    'nx.jpg',
    'py.jpg',
    'ny.jpg',
    'pz.jpg',
    'nz.jpg'
]);
//场景添加背景
scene.background = envTexture;
//场景的物体添加环境贴图(无默认情况使用)
scene.environment = envTexture;

const sphereGeometry = new THREE.SphereGeometry(5, 30, 30);
const sphereMaterial = new THREE.MeshStandardMaterial({
    roughness: 0,//设置粗糙程度
    metalness: 1,//金属度
    envMap:envTexture,

});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
scene.add(sphere);




//光照
const ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient);

const directionalLight = new THREE.DirectionalLight(0xffffff, 0.05);
directionalLight.position.set(10,10,10);
directionalLight.lookAt(scene.position);
scene.add( directionalLight );


//相机
camera = new THREE.PerspectiveCamera(
    60,
    window.innerWidth / window.innerHeight,
    1,
    2000,
);
camera.position.set(10,10,20);
camera.lookAt(scene.position);
scene.add(camera);


//渲染器
renderer = new THREE.WebGLRenderer({
    //防止锯齿
    antialias: true,
});
renderer.setSize(window.innerWidth, window.innerHeight);
// renderer.setClearColor(0xb9d3ff, 1);
document.body.appendChild(renderer.domElement);

//鼠标控制器
const controls = new OrbitControls(camera, renderer.domElement);
//阻尼 必须在 render函数调用  controls.update();
controls.dampingFactor = true;
controls.autoRotate=true

const stats=new Stats()
document.body.appendChild(stats.dom);
function render () { 
   
    renderer.render(scene, camera);
    requestAnimationFrame(render);
    controls.update();//调用
    stats.update()
}
render();


//全屏操作
window.addEventListener('dblclick', () => { 
    //查询是否全屏
    let isFullScene = document.fullscreenElement;
    console.log(isFullScene);
    if (!isFullScene) {
        renderer.domElement.requestFullscreen();
    }
    else { 
        document.exitFullscreen();
    }
})

//自适应
window.addEventListener('resize', () => { 
    //宽高比
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(window.devicePixelRatio);//设置像素比

})

//界面操作
const gui = new dat.GUI();

//操作物体位置
gui
    .add(sphere.position, 'x')
    .min(0)
    .max(10)
    .step(0.1)
    .name('X轴移动')
    .onChange((value) => {
        console.log('修改的值为' + value);
    })
    .onFinishChange((value) => {
        console.log('完全停止' + value);
    });
//操作物体颜色
const colors = {
    color: '#0000ff',
};
gui
    .addColor(colors, 'color')
    .onChange((value) => {
        //修改物体颜色
        sphere.material.color.set(value);
    });

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/913.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#基础·补丁

文章目录一 命名空间二字符串2.1 System.String类2.2 StringBuilder类三 正则表达式3.1 什么是正则表达式&#xff1f;3.2 查找举例3.3 重复描述字符举例3.4 反义字符3.5 基本语法元字符3.6 定位元字符3.7 择一匹配3.8 分组一 命名空间 二字符串 字符串类 System.String(strin…

python数据分析之numpy

数据分析之Numpy 1、Numpy的数组对象及其索引 import numpy as npimport numpy as npanp.array([1,2,3,4]) print(a) bnp.array([2,3,4,5]) print(b)print(ab)产生数组 从列表产生数组&#xff1a; list_array[1,2,3,4] anp.array(list_array) print(a)从列表传入&#xff…

PCB设计很简单?生产问题才是考验工程师能力的标准!

BOM清单有误 SMT产线&#xff1a;物料封装怎么和PCB焊盘不一致呢&#xff1f;停线排查。 仓库&#xff1a;我是按照BOM清单发的物料。 硬件研发&#xff1a;哎&#xff0c;BOM整理时马虎了。 过孔焊盘问题 “ 连锡问题 产线维修&#xff1a;怎么这么多连锡导致不良的产品&…

【安信可NB-IoT模组EC系列应用笔记⑧】用NB-IoT模组EC系列了解LwM2M协议并接入云平台

文章目录前言一、测试准备1、硬件准备2、云平台准备二、云平台连接1.注册入网2.读取IMSI及IMEI3.利用IMSI及IMEI创建设备4.LwM2M连接云平台设备三、 数据互交1.ATMIPLNOTIFY 通知属性变化2.ATMIPLREADRSP 返回读取结果3.ATMIPLWRITERSP 发送写入结果4.ATMIPLEXECUTERSP 发送执行…

1.uniapp全局状态管理

概念&#xff1a;把多个组件之间共享数据抽离出来&#xff0c;通过一个“单例模式”进行管理 工具&#xff1a;具备全局状态管理的库 Vuex:全局状态管理中的库 步骤&#xff1a; 1.建立Store文件夹 2.建立index.js文件 3.在main.js中注册Vue插件 4.测试Vuex是否导入成功 …

面试面麻了,别再为难软件测试人员了···

前言 有不少技术友在测试群里讨论&#xff0c;近期的面试越来越难了&#xff0c;要背的八股文越来越多了,考察得越来越细&#xff0c;越来越底层&#xff0c;明摆着就是想让我们徒手造航母嘛&#xff01;实在是太为难我们这些测试工程师了。 这不&#xff0c;为了帮大家节约时…

基于单片机的双足仿生运动机器人的设计

目录 1 概述 1 1.1 研究背景及意义 1 1.2 机器人的应用领域及发展现状 1 1.2.1 应用领域 1 1.2.2 发展现状 1 1.3 双足机器人设计要求 2 1.3.1 硬件部分 2 1.3.2 软件部分 2 2 系统方案设计 3 2.1 主控芯片选择 3 2.2 机器人自由度选择 3 2.3 驱动方案选择 3 2.4 双足机器人的步…

00后表示真干不过,部门新来的00后测试员已把我卷崩溃,想离职了...

在程序员职场上&#xff0c;什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事&#xff0c;可遇不可求&#xff0c;向他学习还来不及呢。 真正让人反感的&#xff0c;是技术平平&#x…

web安全之信息收集

&#x1f4aa;&#x1f4aa; web安全之信息收集1.网络入口/信息1.1网络拓扑信息1.2 IP信息1.3线下网络2.域名信息2.1Whios2.2搜索引擎搜索2.3. 第三方查询2.4. ASN信息关联2.5. 域名相关性2.6. 网站信息利用2.7. HTTPS证书2.8. CDN2.9. 子域爆破3.端口信息3.1常见端口3.2端口扫…

具有现代设计和最新Bootstrap版本的数字市场HTML模板

DegMark是具有现代设计和最新Bootstrap版本的数字市场HTML模板。凭借优秀的设计很容易创建虚拟商品交易网站&#xff0c;比如图片素材在线交易&#xff0c;视频文件交易&#xff0c;代码交易等虚拟商品交易。 主要特色 Bootstrapv5 移动响应 FontAwesome图标 jQuery增强 …

metaRTC Visual Studio编译指南

概述 metaRTC windows版本提供qt和vs2019两种编译支持&#xff0c;vs2019编译工程支持从metaRTC6.0版本开始&#xff0c;qt编译在B站有视频教程。 metaRTC5 windows版编译教程_哔哩哔哩_bilibilimetartc5编译教程&#xff0c;windows版本只支持msvc,下载所带第三方库为msvc20…

生物信息-快速序列比对-edlib包安装与使用方法-python和dll

安装 下载&#xff1a;https://github.com/Martinsos/edlib cd build && cmake -D CMAKE_BUILD_TYPERelease .. && make升级cmake https://cmake.org/download/ 下载tar.gz包&#xff0c;我这里下载的是&#xff1a; 拷贝到 /home/xxx/app 下解压&#xff…

初识C#事件

文章目录一 事件1 抛砖引玉案例1.1工具人下楼案例1.1.1 ToolMan.cs1.1.2 LazyMan.cs1.1.3 Program.cs1.1.4 测试结果1.1.5 升级到事件二 委托和事件的区别和联系一 事件 1 抛砖引玉案例 订阅和发布机制 比如说&#xff0c;我要下楼去吃饭&#xff0c;正常情况下我会问一下室友…

设计模式之适配器模式

设计模式之适配器模式 文章目录设计模式之适配器模式1. 定义2. 类型3. 场景4. 优点5. 缺点6. 适配器扩展6. 相关适配器模式7. coding7.1 被 适配者方法7.2 接口7.3 接口的实现7.4 适配者适配被适配者达到Target 目标7.5 类适配器的实现方式&#xff0c;其他的都不变8. 源码解析…

【Django】REST_Framework框架——序列化器serializers源码解析

一、序列化器类——Serializer 1、序列化器的作用 序列化器的使用分两个阶段&#xff1a; 1、在客户端请求时&#xff0c;使用序列化器可以完成对数据的反序列化&#xff08;将字典格式的数据转化为模型对象&#xff09;。 2、在服务器响应时&#xff0c;使用序列化器可以完…

网络原理——No.4 传输层_TCP协议中的延迟应答, 捎带应答, 面向字节流与TCP的异常处理

JavaEE传送门JavaEE 网络原理——No.2 传输层_TCP的连接管理 网络原理——No.3 传输层_TCP的滑动窗口, 流量控制与拥塞控制 目录延迟应答捎带应答面向字节流粘包问题TCP 中的异常处理(连接异常)TCP 和 UDP 的应用场景延迟应答 一种提高传输效率的机制, 又是基于流量控制, 来引…

Appinventor——蓝牙app(蓝牙遥控器、串口助手、温湿度显示、切换界面蓝牙依旧保持连接)

App Inventor由谷歌实验室开发&#xff0c;移交麻省理工学院&#xff0c;是一款图形化编程环境&#xff0c;不需要复杂的变成语言&#xff0c;采用搭积木的方式编程&#xff0c;只需将组件拖入即可&#xff0c;简直就是不爱编程党的超级福音 本文搭建了一个蓝牙app&#xff0c…

【CSS】CSS基础认知【CSS基础知识详解】

&#x1f338;大家好&#xff0c;我是花无缺&#xff0c;一枚热爱生活的新时代青年&#xff0c;感谢你的阅读&#x1f970;~ &#x1f468;‍&#x1f4bb;个人主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专…

女朋友说她累了之后依然在线,于是20行代码写了个小工具康康发生了什么

近发现女朋友一到晚上总是很忙的样子&#xff0c; 每晚匆匆忙忙道过晚安就说自己累了去睡觉。 是我哪里做的不对吗… 睡就睡了&#xff0c;可是&#xff0c;QQ头像却会偶尔亮起来&#xff0c; 我非常担心&#xff0c;是不是账号被盗了呢&#xff1f; 然后&#xff0c;就想帮…

Django全家桶

Django框架从入门到高级 &#xff08;一&#xff09;Django入门 Web应用 详细地址见&#xff1a;https://blog.csdn.net/DiligentGG/article/details/126606099?spm1001.2014.3001.5501 Web框架本质 web框架本质上可以看成是一个功能强大的socket服务端&#xff0c;用户的…