当前位置: 首页 > news >正文

Three.js学习6:透视相机和正交相机

一、相机

相机 camera,可以理解为摄像机。在拍影视剧的时候,最终用户看到的画面都是相机拍出来的内容。

Three.js 里,相机 camera 里的内容就是用户能看到的内容。从这个角度来看,相机其实就是用户的视野,就像用户的眼睛

Three.js 主要有四种不同的相机模式:

  • 透视相机 PerspectiveCamera:具有透视效果,近大远小,也是用的最多的相机。

  • 正交相机 OrthographicCamera:不具有透视效果,所有的元素的尺寸大小都是相同的,不管距离。

  • 立体相机 StereoCamera:主要做VR用的。就是让左右视觉有点点不一样的相机。

  • 立方体相机 CubeCamera:主要用作反射镜面纹理。

本文主要讨论透视相机和正交相机。

前面案例中应用到的轨道控制器,名为轨道,其实控制的就是相机的视角。

 二、透视相机

透视相机(PerspectiveCamera)中的物体具有“近大远小”的特点,是3D场景的渲染中使用得最普遍的投影模式。

1. 参数解析

const camera = new THREE.PerspectiveCamera(fov, aspect, near, far );

其参数分别为:

  1. fov :摄像机视锥体垂直视野角度,以角度来表示。默认值是50

  2. aspect :摄像机视锥体宽高比:默认值为 1,一般用渲染器到宽高比

  3. near:摄像机视锥体近截面,默认值是0.1

  4. far:摄像机视锥体远截面,默认值是2000

const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
scene.add( camera );

 只有在视锥体范围内,近截面和远截面之间的物体才会被渲染出来。

Three.js 编辑器里视锥体的样子:

 

可以通过点语法的形式修改相机视锥体的参数,但是必须调用camera.updateProjectionMatrix() 方法,让修改生效。

const camera = new THREE.PerspectiveCamera(50, winW/winH,1, 10);
camera.near = 5;    // 修改参数
camera.far = 37;
camera.updateProjectionMatrix();   // 让参数修改生效

2. 修改相机坐标

因为,相机默认在原点上,物体也默认在原点上。所以,要看到物品,要把相机往后挪动位置,也既修改 z 轴位置。

// 调整相机位置 x,y,z
camera.position.z = 0;
camera.position.x = 0;
camera.position.y = 10;// 或者 
camera.position.set(0,0,10);

3. 镜头对准物体

不过有时候,移动相机的时候,相机必须要盯着目标物体,避免物体跑出视野之外。

camera.lookAt( Xmesh.position ); // 相机镜头盯着x物体

也可以对准某个具体的位置:

camera.lookAt(new THREE.Vector3(x,y,z));

4. 缩放镜头

camera.zoom = 4;
camera.updateProjectionMatrix();   // 让参数修改生效

获取或者设置摄像机的缩放倍数,其默认值为1

  • >1:镜头里的物体会被放大

  • <1:物体会被缩小

  • =1:物体正常大小

必须调用camera.updateProjectionMatrix() 方法,让修改生效。

三、正交相机

正交相机(OrthographicCamera),无论物体距离相机距离远或者近,在最终渲染物体的大小都保持不变。

主要用于渲染 2D 场景或者UI元素。如下图所示:

 1. 参数解析

const camera = new THREE.OrthographicCamera(OrthographicCamera( left, right, top, bottom, near, far);
scene.add( camera );

其参数依次分别为:

  • left : 摄像机视锥体左侧面

  • right : 摄像机视锥体右侧面。left 与 right 互为反数。

  • top:摄像机视锥体上侧面

  • bottom: 摄像机视锥体下侧面。top 与 bottom 互为反数。

  • near : 摄像机视锥体近截面。其默认值为0.1

  • far: 摄像机视锥体远截面。其默认值为2000

这几个参数刚好组成一个立方体。

 例如:

const k = winW / winH; //canvas画布宽高比
const s = 2; // 显示控制系数。
const camera = new THREE.OrthographicCamera( -s*k, k*s, s, -s, 0.1, 2000 );
camera.position.set(8,8,8);
scene.add( camera );

为了保持照相机的横竖比例,需要保证 (right - left)(top - bottom) 的比例与 Canvas(也就是渲染器)宽度与高度的比例一致。所以才有了两个变量 k、s。

  • 变量 k:render 渲染的宽高比。因为,正交相机默认渲染的是一个正方形,但是我们渲染的范围(canvas)不一定是一个正方形。正交相机区域将被拉伸以适合我们的矩形画布,因此我们需要使用画布的宽高比。

  • 变量 S 是正交相机显示控制系数。值越小,画面越大。反之,画面越小。如果为1,画面会很大。所以,这里用“单位”的2倍。当然,也可以根据需要自行调整数据。

Three.js 编辑器里正交相机视锥体的样子:

跟透视相机一样,可以通过点语法的形式修改相机视锥体的参数,但是必须调用camera.updateProjectionMatrix() 方法,让修改生效。  

2. 正交相机例子

let winW = window.innerWidth;
let winH = window.innerHeight;// 场景
const scene = new THREE.Scene();
scene.background = new THREE.Color("#cccccc");// 网格辅助器
const grid = new THREE.GridHelper(1000,10);
scene.add(grid);// 物体
const geometry = new THREE.BoxGeometry(100,100,100);
const material = new THREE.MeshBasicMaterial({color:"#f00"
});
const mesh = new THREE.Mesh( geometry, material );
mesh.position.set(0,0,0);
scene.add( mesh );// 正投影相机案例
const k = winW / winH; //canvas画布宽高比
const s = 2; // 显示控制系数。网格单位*2
const camera = new THREE.OrthographicCamera( -s*k, k*s, s, -s, 0.1, 2000 );
camera.position.set(8,8,8);
scene.add( camera );// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize( winW, winH );
document.body.appendChild( renderer.domElement );
renderer.render(scene, camera);// 轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.update();
controls.addEventListener(function(){console.info( camera.position );
});// 动画
function aniFun(){renderer.render( scene, camera );controls.update();requestAnimationFrame( aniFun );
}
aniFun();

可以看到,正交相机的图像是没有近大远小的透视感的。

四、相机切换示例

 html:

<div class="btns"><button type="button"  id="tsBtn">透视相机</button><button type="button"  id="zjBtn">正交相机</button><h1 id="tit">透视相机</h1>
</div><script type="importmap">{"imports":{"three":"./js/three.module.min.js","three/addons/":"./js/jsm/"}}
</script>
<script type="module" src="./js/myjs5-3.js"></script>

JS:

import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";let scene,camera,controls, grid,renderer;
let winW = window.innerWidth,winH = window.innerHeight;let  tsBtn = document.getElementById("tsBtn"),zjBtn = document.getElementById("zjBtn"),tit = document.getElementById("tit");// 场景
scene = new THREE.Scene();
scene.background = new THREE.Color("#cccccc");// 透视相机
function pCamera(){camera = new THREE.PerspectiveCamera(50, winW/winH,1, 1000);camera.position.set( 8,8,8 );camera.lookAt( scene.position );scene.add( camera );
}// 正交相机
function oCamera(){const k = winW / winH; //canvas画布宽高比const s = 8; // 显示控制系数。camera = new THREE.OrthographicCamera( -s*k, k*s, s, -s, 0.1, 2000 );camera.position.set(8,8,8);camera.lookAt( scene.position );scene.add( camera );
}// 渲染器
function renderFun(){renderer = new THREE.WebGLRenderer();renderer.setSize( winW, winH );document.body.appendChild( renderer.domElement );
}// 网格辅助
function gridHelperFun(){grid = new THREE.GridHelper(10,10);scene.add(grid);
}// 立方体
function cubeFun(){let geometry = new THREE.BoxGeometry(1,1,1);let metiral = new THREE.MeshBasicMaterial({color:"#ff3300"});let mesh = new THREE.Mesh( geometry, metiral);scene.add( mesh );
}// 函数调用
pCamera();
renderFun();
gridHelperFun();
cubeFun();renderer.render(scene, camera);// 动画渲染
function animateFun(){// 渲染renderer.render( scene, camera);requestAnimationFrame(animateFun);
}
animateFun();// 按钮事件
tsBtn.addEventListener("click",function(){pCamera();renderer.render(scene, camera);tit.innerHTML = "透视相机";
});
zjBtn.addEventListener("click",function(){oCamera();renderer.render(scene, camera);tit.innerHTML = "正交相机";
});

相关文章:

Three.js学习6:透视相机和正交相机

一、相机 相机 camera&#xff0c;可以理解为摄像机。在拍影视剧的时候&#xff0c;最终用户看到的画面都是相机拍出来的内容。 Three.js 里&#xff0c;相机 camera 里的内容就是用户能看到的内容。从这个角度来看&#xff0c;相机其实就是用户的视野&#xff0c;就像用户的眼…...

❤ React18 环境搭建项目与运行(地址已经放Gitee开源)

❤ React项目搭建与运行 环境介绍 node v20.11.0 react 18.2 react-dom 18.2.0一、React环境搭建 第一种普通cra搭建 1、检查本地环境 node版本 18.17.0 检查node和npm环境 node -v npm -v 2、安装yarn npm install -g yarn yarn --version 3、创建一个新的React项目…...

2024 RTE行业(实时互动行业)人才发展学习总结

解决方案 人才画像 开发者人才素质要求&#xff1a; 具备多个领域的技术知识注重团队合作&#xff0c;具备协作能力以用户为导向的用户体验意识具备创新思维和解决问题的能力需快速响应行业变化和持续的学习能力具备项目管理能力 学习和吸收新知识的渠道 RTE人才分类...

92.网游逆向分析与插件开发-游戏窗口化助手-显示游戏数据到小助手UI

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;游戏窗口化助手的UI设计-CSDN博客 码云地址&#xff08;游戏窗口化助手 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;e8116af3a7b0186adba…...

Stable Diffusion 模型下载:majicMIX fantasy 麦橘幻想

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 非常推荐的一个非常绚丽、充满幻想的大模型&#xff0c;由国人“Merjic”发布&#xff0c;下载量颇高。这个模型风格炸裂&#xff0c;远距离脸部需要inpaint以达成…...

docker compose安装minio

要使docker-compose管理的容器&#xff08;如MinIO&#xff09;在系统启动时自动启动&#xff0c;你需要使用Docker的重启策略。在你的docker-compose.yml文件中为MinIO服务添加restart策略即可实现这一目标。restart: always指令确保了在容器退出时总是重新启动容器&#xff0…...

二、SSM 整合配置实战

本章概要 依赖整合和添加控制层配置编写(SpringMVC 整合)业务配置编写(AOP/TX 整合)持久层配置编写(MyBatis 整合)容器初始化配置类整合测试 2.1 依赖整合和添加 数据库准备 数据库脚本 CREATE DATABASE mybatis-example;USE mybatis-example;CREATE TABLE t_emp(emp_id INT…...

『运维备忘录』之 Yum 命令详解

运维人员不仅要熟悉操作系统、服务器、网络等只是&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…...

CSS中可继承与不可继承属性有哪些

一、无继承性的属性 1.display&#xff1a;规定元素应该生成的框的类型 属性值作用none元素不显示&#xff0c;并且会从文档流中移除。block块类型。默认宽度为父元素宽度&#xff0c;可设置宽高&#xff0c;换行显示。inline行内元素类型。默认宽度为内容宽度&#xff0c;不…...

Zephyr NRF7002 实现AppleJuice

BLE的基础知识 ble的信道和BR/EDR的信道是完全不一样的。但是范围是相同的&#xff0c;差不多也都是2.4Ghz的频道。可以简单理解为空中有40个信道0~39信道。两个设备在相同的信道里面可以进行相互通信。 而这些信道SIG又重新编号&#xff1a; 这个编号就是把37 38 39。 3个信道…...

(已解决)vue+element-ui实现个人中心,仿照原神

差一个个人中心页面&#xff0c;看到了这个博主的个人中心&#xff0c;真的很不错 地址&#xff1a;vueelement仿原神实现好看的个人中心 最终效果&#xff1a;...

Webpack插件浅析

常用的webpack插件功能介绍&#xff1a; 1.HotModuleReplacementPlugin 模块热更新插件。Hot-Module-Replacement的热更新是依赖于webpack-dev-server&#xff0c;有时是在打包文件改变时更新打包文件或者重新加载刷新整个页面&#xff0c;HMR是只更新修改的部分。 HotModul…...

【Java 数据结构】反射

反射 1 定义2 用途(了解)3 反射基本信息4 反射相关的类&#xff08;重要&#xff09;4.1 Class类(反射机制的起源 )4.1.1 Class类中的相关方法(方法的使用方法在后边的示例当中) 4.2 反射示例4.2.1 获得Class对象的三种方式4.2.2 反射的使用 5、反射优点和缺点 1 定义 Java的反…...

LangChain结合通义千问的自建知识库

LangChain结合通义千问的自建知识库 在使用了通义千问API了之后&#xff0c;下一步就是构建知识库文档&#xff0c;使用了比较有名的LangChian&#xff0c;最后成果将自己的txt生成了知识向量库&#xff0c;最后我还把自己的论文生成了一个知识向量库&#xff0c;然后问他我的…...

【证书管理】实验报告

证书管理实验 【实验环境】 ISES客户端 【实验步骤】 查看证书 查看证书详细信息 选择任意证书状态&#xff0c;在下方“证书列表”中出现符合要求的所有证书。在“证书列表”中点击要查看证书&#xff0c;在右侧“证书详细信息”栏出现被选证书信息。 上述操作如图1.2.…...

App Store外区账号分享

App Store外区账号分享及注意事项 外区苹果ID分享指南什么是外区苹果ID&#xff1f;为什么需要外区苹果ID&#xff1f;获取方法分享外区苹果ID的注意事项方式2获取步骤 外区苹果ID分享指南 在数字时代&#xff0c;我们的生活与各种应用和服务紧密相连。 对于苹果用户而言&#…...

判断字符串是否包含正则表达式默认的特殊字符c++

判断字符串是否包含正则表达式默认的特殊字符 业务描述&#xff1a; 上层配置的字符列表中&#xff0c;既有准确的字符串&#xff0c;又有可以进行正则匹配的字符串&#xff0c;这时候需要区分出来那些是正则匹配的字符串。 思路: 判断字符串中&#xff0c;是否存在正则表达…...

【蓝桥杯选拔赛真题64】python数字塔 第十五届青少年组蓝桥杯python 选拔赛比赛真题解析

python数字塔 第十五届蓝桥杯青少年组python比赛选拔赛真题 一、题目要求 (注:input()输入函数的括号中不允许添加任何信息) 提示信息: 数字塔是由 N 行数堆积而成,最顶层只有一个数,次顶层两个数,以此类推。相邻层之间的数用线连接,下一层的每个数与它上一层左上…...

javaEE - 23( 21000 字 Servlet 入门 -1 )

一&#xff1a;Servlet 1.1 Servlet 是什么 Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一个 web app. 构建动态页面的技术有很多, 每种语言都有一些相关的库/框架来做这件事&#xff0c;Servlet 就是 Tomcat 这个 HTTP…...

【sentinel流量卫兵搭建与微服务整合】

sentinel流量卫兵搭建与微服务整合 搭建sentinel dashboard控制台微服务整合搭建sentinel dashboard控制台 1、下载 官网链接 由于官网github网络原因,导致长时间下载失败。 网盘链接 网盘提取码:dwgj 2、运行 将下载jar包放在任意非中文、不包含特殊字符的目录下,重名为…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

WEB3全栈开发——面试专业技能点P4数据库

一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库&#xff0c;基于 mysql 库改进而来&#xff0c;具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点&#xff1a; 支持 Promise / async-await&#xf…...

React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?

系列回顾&#xff1a; 在上一篇《React核心概念&#xff1a;State是什么&#xff1f;》中&#xff0c;我们学习了如何使用useState让一个组件拥有自己的内部数据&#xff08;State&#xff09;&#xff0c;并通过一个计数器案例&#xff0c;实现了组件的自我更新。这很棒&#…...