Three.js 实战【1】—— 3D全景视图开发

news2024/11/24 9:25:13

Three.js 实战【1】—— 3D全景视图开发

    • 摘要
  • 1、3D视图Demo
  • 2、准备工作——搭建好一个开发环境
  • 3、RGBELoader——高范围动态图像加载器
  • 4、HDR——高动态范围图像
  • 5、使用HDR实现3D全景视图
  • 6、直接通过图片纹理进行实现

摘要

在现代开发过程当中,3D开发是越来越不可或缺的一部门,在前面的文章当中简单的说明了一些threeJs的基础,从这里开始,我们将对ThreeJs整体进行一定的应用。

1、3D视图Demo

我们先看一下这篇文章主要要实现的一个demo效果,现如今在第三方租房、买房App、或者百度、高德地图上会出现这种全景视图,当手势操作时,他对应的景色也会发生一定的变化。又或者你最近刷抖音看到了HM玩的图寻,给了一张可以旋转的3D全景图片,然后找这张图片在哪拍摄的,你可能会好奇这种效果在前端是如何实现的。这就是这篇文章将会教会你的一个小demo。由于视频过大,直接插入链接,可在该链接查看效果:https://live.csdn.net/v/297465

在这里插入图片描述

2、准备工作——搭建好一个开发环境

在这里创建好一个vue脚手架的项目,这里不做过多的赘述,并且安装threeJs的依赖,创建好一个vue文件的threejs开发的基本模板,也就是对之前介绍的抽离出来放到了vue当中,启动项目查看效果是否出现,这里就简单的添加了一个坐标系用来验证3D效果

<template>
    <div id="home" class="home">
    </div>
</template>
<script>
import * as THREE from 'three'
import {
    OrbitControls
} from 'three/examples/jsm/controls/OrbitControls.js'

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 1);
scene.add(camera);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

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

const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

export default {
    data() {
        return {
            controls: null
        }
    },
    mounted() {
        this.windownEvent()
        document.getElementById('home').appendChild(renderer.domElement);
        this.render()
    },
    methods: {
        windownEvent() {
            window.addEventListener('resize', (e) => {
                // 宽高比
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(window.innerWidth, window.innerHeight);
                renderer.setPixelRatio(window.devicePixelRatio);
            })
        },
        render() {
            renderer.render(scene, camera);
            requestAnimationFrame(this.render);
        },
    }
}
</script>
<style>
html,
body {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
}

#home {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
}
</style>

3、RGBELoader——高范围动态图像加载器

Three.js 中 RGBELoader 是一种用于加载高动态范围图像(High Dynamic Range,HDR)的 Loader,它可以将 .hdr 或 .rgbe 格式的 HDR 图像文件加载到 Three.js 的 WebGL 场景中,并方便地应用于场景渲染和光照等方面。

下面是 RGBELoader 主要的特点和使用方式:

  • 支持 .hdr 和 .rgbe 格式的 HDR 图像。.hdr 格式是包含 HDR 光照信息的图片格式,其中每个像素值通常表示颜色和亮度等信息;.rgbe 格式节省了存储空间,采用纯文本的方式保存 HDR 图像,但需要进行额外的解析和处理操作。
  • 支持流式加载、按需解码、异步数据读取等功能。在加载时,可以设置图片数据类型(UnsignedByteType、FloatType 等),控制是否自动 gamma 校正,以及是否生成 mipmap 等参数。
  • 提供了多种加载结果的返回类型,如 HDRBufferAttribute、DataTexture、CubeTexture 等。这些返回类型可以方便地根据实际需要来进行灵活的结果调整和下一步操作。
  • 可以与其它 Three.js 特性和工具集成。比如,可以将 HDR 图像转换为 cube map 并与 PBR 材质、天空盒、环境映射等一起使用,实现高质量的场景渲染效果。

4、HDR——高动态范围图像

HDR是一种用于表示图像的技术,它可以在不失真地呈现高亮度和阴影细节的情况下,显示更广泛、更丰富的颜色和亮度范围。常见的传统图像格式,如 JPEG、PNG 等都是 LDR (Low Dynamic Range) 图像,其表示的颜色和亮度值受到比较大的限制,并且不能储存超出一定范围的亮度信息。

HDR 图像通常被保存为高精度的 32 位或 16 位浮点数格式,每个像素颜色通道的值可以表示比较大的亮度范围,例如标准化后的亮度值可以达到 0 到 1 之间或更高。使用 HDR 技术,有助于突破 LDR 图像表现能力的瓶颈,解决了过曝和欠曝等高光/暗部细节损失的问题。

相比于 LDR 图像,HDR 图像具有很高的动态范围,支持更加复杂和真实的光影效果。通过处理 HDR 图像,可以对导致渲染物体看上去真实的环境光、反射和折射、散射等进行精确的计算和模拟,从而呈现更真实精细的场景。例如,可以创建栩栩如生的光源、镜面和玻璃材质,产生更自然的阴影和高光反射效果等。

除了在娱乐和游戏领域得到广泛应用外,HDR 技术还被用于物理模拟、医学成像、地球科学、工业制造和计算机视觉等领域。值得一提的是,HDR 图像的制作和处理需要耗费较大的计算资源和专业知识,且其数据量相对较大,需要特殊的压缩技术来减少文件大小。

5、使用HDR实现3D全景视图

在熟悉了一下RGBELoader和HDR大概的就了解了这样子的全景视图是如何做的,就像前面说到的Threejs的纹理一样,我们通过ThreeJs的RGBELoader加载HDR静态文件渲染就完事了。具体如何实现呢?直接看以下代码:

先导入这个RGBELoader加载器,并且引入对应的HDR资源,这里新加了一个方法,通过RGBELoader加载器异步加载这个HDR资源,加载完成之后会得到一个texture纹理,将得到的纹理渲染到场景之上就完成了这个3D全景视图的开发了。最后在mounted生命周期上调用一下这个addHdr方法就实现了效果:也就是:https://live.csdn.net/v/297465

注:当然了这里你也可以不通过import引入HDR,直接将HDR地址写到loadAsync()当中也是一样。但是由于Vue是会先编译的,如果你没有对HDR文件编译打包进行处理,这里直接写路径是找不到这个资源的

import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'
import BOLLROOM from '../assets/hdr/ballroom_4k.hdr'

addHdr() {
	rgbeloader.loadAsync(BOLLROOM).then((texture) => {
		texture.mapping = THREE.EquirectangularReflectionMapping
	    scene.background = texture
        scene.environment = texture
    })
}

这里推荐几个获取HDR资源的网站:

  • polyhaven https://polyhaven.com/zh/hdris
  • 爱给网 https://www.aigei.com/s?q=HDR

6、直接通过图片纹理进行实现

在前面我们可以创建一个3D的正方体,并且我们发现给正方体设置texture的时候可以渲染两面,那这一个的实现思路就是:给正方体设置的大一点,而我们的视角(摄像头)设置到正方体的内部,这样我们看到的就是正方体的内部六个面,而再通过加载图片得到纹理,将纹理依次设置到六个面上,这样从里面看起来依然还是全景视图的效果。看一下代码如何实现:

  • 这里先引入对应六个面的图片,
  • 而后创建一个101010的正方体(此时设置的视角在正方体内部)
  • 创建数组 arr,存储了 6 张图片的路径,用于作为正方体的纹理贴图。
  • 新建数组 boxMaterial,遍历 arr 数组中所有的元素 item,对于每个 item,加载其对应的图片纹理并将其添加到 boxMaterial 数组中创建一个包含图片纹理的 MeshBasicMaterial 对象。
  • 使用上述创建好的 boxMaterial 数组,新建一个 Mesh 对象 cube,并将 geometry 和 boxMaterial 分别传入其中初始化。
  • 将正方体的 geometry 进行缩放 transform,使其在 z 轴方向翻转(因为 WebGL 中 z 轴默认为屏幕内,而 Three.js 中 y 轴默认为屏幕内),从而让正方体可以面向摄像机。
  • 最后通过 scene.add() 方法将正方体 cube 添加到场景中,使其在渲染时显示出来。

查看效果:https://live.csdn.net/v/297468

// 先引入六个面的图片
import ONE from '../assets/img/1.jpg'
import TWO from '../assets/img/2.jpg'
import TWOPLUS from '../assets/img/3.jpg'
import FOUR from '../assets/img/4.jpg'
import FIVE from '../assets/img/5.jpg'
import SIX from '../assets/img/6.jpg'

addBox() {
	const geometry = new THREE.BoxGeometry(10, 10, 10);
    var arr = [ONE, TWO, TWOPLUS, FOUR, FIVE, SIX]
    var boxMaterial = []
    arr.forEach(item => {
    	let textureLoader = new THREE.TextureLoader().load(item)
        	boxMaterial.push(new THREE.MeshBasicMaterial({ map: textureLoader }))
    })
    console.log(boxMaterial)
    const cube = new THREE.Mesh(geometry, boxMaterial);
    cube.geometry.scale(1, 1, -1)
    scene.add(cube);
},

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

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

相关文章

find,which,whereis,grep,bc,uname,free,nano,history指令的语法,功能与选项等

Tips x86_64 与 x64 都是指 64位x86 指的是 32位 find指令的语法&#xff0c;功能与选项 语法&#xff1a;find 目录 -name 文件名功能&#xff1a;在指定的目录之下进行文件查找&#xff08;递归式查找&#xff09;选项&#xff1a;它的选项也非常多&#xff0c;讲个 -name…

【Java 基础】File IO流

文章目录 1. File1.1 File类概述和构造方法1.2 绝对路径和相对路径1.3 File 类的常用方法1.4 递归删除文件夹及其下面的文件 2. IO2.1 分类2.2 字节输出流2.3 字节输入流2.4 文件的拷贝2.5 文件拷贝效率优化2.6 释放资源2.7 缓冲流2.8 编码表 3. commons-io 工具包3.1 API 1. F…

VSCode中安装GPT插件详细教程+gpt4改进

目录 安装插件 A.安装CodeGPT B.安装chatgpt 1.VSCode安装插件&#xff0c;使用本地下载vsix文件 2.获取 ChatGPT API 密钥 3.配置settings.json gpt4和3.5对比 GPT-4主要有三大改进点 局限性 安装插件 AB功能一样&#xff0c;A安装的人最多&#xff0c;GPT具体功能可…

K8s之标签、Node选择器与亲和性详解

文章目录 一、标签1、标签是什么&#xff1f;2、给Pod打标签3、给Node节点打标签4、查看标签资源 二、Node选择器1、nodeName(指定Pod调度到指定Node节点)2、nodeSelector(指定Pod调度到具有指定标签的Node节点) 三、亲和性1、Node亲和性-nodeAffinity2、Pod亲和性-podAffinity…

软件测试项目实战经验附视频以及源码【医疗项目,社区管理,前后端分离项目,银行项目,金融项目,车载项目】

前言&#xff1a; ​​大家好&#xff0c;我是测试小马。 很多初学的测试小白都在烦恼找不到合适的项目去练习&#xff0c;这也是难倒大部分测试小白的一个很常见的问题&#xff0c;项目经验确实是每一个测试非常宝贵的经验&#xff01;这里小马哥给大家找了一些常用的项目合…

AJ-Captcha验证码使用教程源码解读

1.背景 验证码的主要作用是防止机器人恶意使用我们的程序........ 今天我们结束一款强大的验证码组件:aj-captcha 官方文档:AJ-Captcha在线体验 大家一定要认真阅读官方文档 2.项目启动与快速测试 启动后端: 快速页面测试: 使用浏览器访问这个页面 有修改后端源码的情况…

MySQL触发器Trigger加载以及目前局限

GreatSQL社区原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本&#xff0c;使用上与MySQL一致。作者&#xff1a; 亮文章来源&#xff1a;GreatSQL社区原创 概念介绍 首先需要知道MySQL中触发器特点&#xff0c;以及表table…

掌握这些技巧,让你的Facebook文案更具说服力!

面对广告瀑布流般的竞争&#xff0c;如何让自己的Facebook广告脱颖而出&#xff0c;吸引到用户的眼球&#xff0c;成为广告运营人员必须思考的问题。在这个过程中&#xff0c;文案的作用是至关重要的。 优秀的文案不仅可以吸引用户点击&#xff0c;还能让用户产生共鸣&#xf…

K8s scheduler 调度:预选和优选策略

1 环境准备 kube-scheduler是k8s的核心组件之一&#xff0c;主要负责Pod的调度。scheduler通过监听kube-apiserver&#xff0c;查询未分配 Node的Pod&#xff0c;根据配置的调度策略&#xff0c;将Pod调度到最优的工作节点上&#xff0c;从而高效、合理地利用k8s集群资源。 在m…

shell之数组

一. 关于数组的命令 1. 定义数组 数组名(value0 value1 value2 …) arr(元素1 元素2 元素3 ...) echo ${arr[]}数组名([0]value [1]value [2]value…" arr ([下标1]值1 [下标2]值2 ....) echo ${array3[]}列表名"value0 value1 value2 list"值1 值2 值3 ..…

一文解读spring中事务管理

目录 声明式事务概念 事务基本概念 ①什么是事务 ②事务的特性 编程式事务 声明式事务 基于注解的声明式事务 准备工作 测试无事务情况 加入事务 Transactional的使用 事务属性&#xff1a;只读 事务属性&#xff1a;超时 事务属性&#xff1a;回滚策略 事务属性…

华为OD机试真题 Java 实现【寻找链表的中间结点】【2023Q1 100分】

一、题目描述 给定一个单链表 L&#xff0c;请编写程序输出 L中间结点保存的数据。如果有两个中间结点&#xff0c;则输出第二个中间结点保存的数据。 例如&#xff1a; 给定 L 为 1 -> 7 -> 5&#xff0c;则输出应该为 7; 给定 L 为 1 -> 2 -> 3 -> 4&#…

微服务简介,SpringCloud Alibaba Nacos的安装部署与使用,Nacos集成springboot实现服务注册

目录 一.认识微服务 1.0.学习目标 1.1.单体架构 单体架构的优缺点如下&#xff1a; 1.2.分布式架构 分布式架构的优缺点&#xff1a; 1.3.微服务 微服务的架构特征&#xff1a; 1.4.SpringCloud 1.5Nacos注册中心 1.6.总结 二、Nacos基本使用安装部署服务注册 &am…

聊一聊适配器模式

接口不能用&#xff1f;行&#xff0c;我帮你适配 一、概述 适配器模式&#xff08;Adapter&#xff09;&#xff0c;是23种设计模式中的结构型模式之一&#xff1b;它就像我们电脑上接口不够时&#xff0c;需要用到的拓展坞&#xff0c;起到转接的作用。它可以将新的功能和原…

SCS【26】单细胞细胞间通信第二部分通信网络的系统分析(CellChat)

桓峰基因公众号推出单细胞生信分析教程并配有视频在线教程&#xff0c;目前整理出来的相关教程目录如下&#xff1a; Topic 6. 克隆进化之 Canopy Topic 7. 克隆进化之 Cardelino Topic 8. 克隆进化之 RobustClone SCS【1】今天开启单细胞之旅&#xff0c;述说单细胞测序的前世…

《微服务实战》 第十一章 Spring Cloud Alibaba nacos配置中心

前言 Nacos 提供用于存储配置和其他元数据的 key/value 存储&#xff0c;为分布式系统中的外部化配置提供服务器端和客户端支持。使用 Spring Cloud Alibaba Nacos Config&#xff0c;您可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。 Spring Cloud Aliba…

【C++ 入坑指南】(08)循环

文章目录 一、while 循环二、do...while 循环三、for 循环四、嵌套循环五、跳转语句5.1 break 语句5.2 continue 语句5.3 goto 语句 有的时候&#xff0c;可能需要多次执行同一块代码。一般情况下&#xff0c;语句是顺序执行的&#xff1a;函数中的第一个语句先执行&#xff0c…

c++ 11标准模板(STL) std::set(五)

定义于头文件 <set> template< class Key, class Compare std::less<Key>, class Allocator std::allocator<Key> > class set;(1)namespace pmr { template <class Key, class Compare std::less<Key>> using se…

Java中的线程通信的几种方式

Java中的线程间通信是指不同线程之间相互协作&#xff0c;以完成一些复杂的任务或实现某些功能的过程。线程间通信主要包括两个方面&#xff1a;线程之间的互斥和同步&#xff0c;以及线程之间的数据共享和通信。Java提供了多种方式来实现线程间通信&#xff0c;本文将介绍Java…

Java | 一分钟掌握定时任务 | 5 - Spring Task

作者&#xff1a;Mars酱 声明&#xff1a;本文章由Mars酱原创&#xff0c;部分内容来源于网络&#xff0c;如有疑问请联系本人。 转载&#xff1a;欢迎转载&#xff0c;转载前先请联系我&#xff01; 前言 多线程解决了并发阻塞问题&#xff0c;但是不能方便的表达我们的定时方…