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

记录下three.js学习过程中不理解问题①

1、透视相机(persperctive)参数理解

const fov = 75;指的是垂直方向的视野范围。

      摄像机视角(fov = 75)
             👁️
            /   \
           /     \     ← 这个夹角就是 75°
          /       \
         /         \
        /___________\  
     near         far

 

摄像机(你)看向前方:
  👁️ —— fov 是你张开眼睛的角度(决定你能看到多广)
   |
  / \
 /   \       ← 看得见的区域(远处的 pyramid)= frustum
|     |     ← 视锥体(frustum)从 near 到 far 之间才看得见
 near        ← 最近 0.1 米
   |
   |
 far         ← 最远 5 米

参数通俗记忆作用
fov视角开多大决定上下看得多少
aspect屏幕长宽比不设置好画面会拉伸
near最近看多少太近的东西不显示
far最远看多远太远的东西不显示

1. 摄像机默认朝向

  • 摄像机默认看向 Z 轴的负方向(即从 z 正方向往 z 负方向看)。

  • 摄像机“上面”是 Y 轴正方向。

2. 为什么要把摄像机往后移?

  • 你的立方体放在坐标原点 (0,0,0)

  • 如果摄像机位置也是原点,那它就在立方体里面,看不到立方体。

  • 所以要把摄像机沿 z 轴正方向往后移动,比如设置 camera.position.z = 2,让摄像机离立方体远一点,这样才能“看到”立方体。

4. 宽高比对视野的影响

  • 画布宽度是高度的两倍(比如300×150像素),宽高比 = 2。

  • 垂直方向视角是你设置的75度,但水平方向视角会更大,因为画布宽了2倍。

  • 也就是说,水平视角会“拉宽”你的视野,让你能看到更宽的范围。

  • fov=75°是垂直方向的视角;

  • 画布宽高比=2,意味着水平视角比75°更大;

  • 这样才能保证3D画面在宽屏幕上完整显示,不会裁剪或变形。

  • . 视觉效果
  • 这个宽视角有点类似人眼的视野宽度:
    人眼上下视角比左右视角窄,因为你眼睛是水平放置的。

  • 在你的三维场景里,水平视角比75°大(可能是100度、120度等),让你能更广阔地看到左右的物体。

requestAnimationFrame 是浏览器提供的一个高效的动画方法,专门用来让页面里的动画“连续播放”。

工作原理:

  1. 它会告诉浏览器:“我准备好下一帧动画了,帮我安排合适的时间来刷新画面。”

  2. 浏览器会在每一帧合适的时间调用你指定的函数(比如更新旋转角度,重新绘制立方体)。

  3. 这个调用是循环的:每次画完一帧动画后,程序又调用自己,形成了动画的“循环”。为

     为什么不用普通的 setIntervalsetTimeout

  1. requestAnimationFrame 会根据屏幕刷新率来执行动画,动画更流畅,不会卡顿。

  2. 当页面不可见时(切换标签页),它会自动暂停动画,节省性能和电量。

  3. 更适合做基于视觉的动画和绘图。

    function render(time) {time *= 0.001;  // 将时间单位变为秒cube.rotation.x = time;cube.rotation.y = time;renderer.render(scene, camera);requestAnimationFrame(render);
    }
    requestAnimationFrame(render);

 

requestAnimationFrame(render); 的意思就是:

  • 告诉浏览器“请在下次重绘时调用 render 函数”。

  • 浏览器调用 render 时,会自动传入一个时间戳 time 参数,这个时间戳是当前页面从加载开始经过的毫秒数。

所以你不用自己传 time,浏览器帮你传进去,方便你根据时间来做动画计算。

总结一句话:

调用 requestAnimationFrame(render) 后,浏览器会自动给 render 函数传入时间戳 time 参数。

 

弧度和角度的关系

  • 一圈是360度。

  • 360度 = 2π弧度(π ≈ 3.1416)

  • 所以一圈的弧度就是:

2×π≈6.2832弧度

这里旋转角度用弧度表示time是经过time *= 0.001后单位为秒的时间。

也就是说,

  • 当时间为1秒时,旋转角度是1弧度。

  • 当时间为6.2832秒时,旋转角度是6.2832弧度,也就是一整圈。

让相机的视野始终和画布(canvas)保持一致比例,防止拉伸变形。

const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
  • canvas.clientWidth / canvas.clientHeight:获取实际画布宽高比(比如 800px / 400px = 2)

  • camera.aspect:更新相机的宽高比

  • camera.updateProjectionMatrix():重新计算相机的投影矩阵(必须的,不然相机不知道你改了宽高比)

为什么画面会“模糊”或“块状化”?

因为:

canvas 的 CSS显示尺寸像素分辨率(绘图缓冲区)不一致。

<canvas style="width: 800px; height: 600px"></canvas>

如果你没设置它的像素尺寸,浏览器默认是 300x150px
也就是说你让它显示为 800×600,但实际里面的像素分辨率只有 300×150,就像你用一张 300×150 的图片硬撑到 800×600,当然糊了!

正确做法:让 canvas 的像素尺寸 = CSS 尺寸

在 Three.js 中,我们使用这个方法调整 canvas 的 绘图缓冲区 大小:

renderer.setSize(width, height, false);
  • widthheight:用 canvas 的 clientWidthclientHeight

  • false:表示 不要自动改 CSS 大小,让 CSS 控它。

封装一个自动检测并更新的函数

function resizeRendererToDisplaySize(renderer) {const canvas = renderer.domElement;const width = canvas.clientWidth;const height = canvas.clientHeight;const needResize = canvas.width !== width || canvas.height !== height;if (needResize) {renderer.setSize(width, height, false);}return needResize;
}

 

用法:
在每一帧 render() 里判断画布有没有大小变化,有就更新相机:

function render(time) {time *= 0.001;if (resizeRendererToDisplaySize(renderer)) {const canvas = renderer.domElement;camera.aspect = canvas.clientWidth / canvas.clientHeight;camera.updateProjectionMatrix();}renderer.render(scene, camera);requestAnimationFrame(render);
}
Canvas 实际尺寸CSS 尺寸结果
300x150800x600模糊(块状)
800x600800x600清晰 ✅

以利用 resizeRendererToDisplaySize() 的返回值判断:

“这帧有没有发生尺寸改变?”

  • 如果有,除了设置 renderer,还要更新 camera 的宽高比。

 

http://www.xdnf.cn/news/927955.html

相关文章:

  • 测试(面经 八股)
  • 《真假信号》速读笔记
  • Python爬虫实战:研究Unirest库相关技术
  • 王劲松《人民日报》撰文 重读抗战家书不忘来时路
  • Windows小说阅读软件推荐
  • Linux 文件系统核心:inode 与 block 深度解析(附实战案例与源码级原理)
  • 618来了,推荐京东云服务器
  • ROS C++ 实现消息通信与服务通信
  • 交叉熵损失函数和极大似然估计是什么,区别是什么
  • 关于队列的使用
  • 道路运输安全员考试分为哪些科目,各科目重点考察什么?
  • scratch农场小鸡 2024年全国青少年信息素养大赛 图形化编程 scratch变成挑战赛 复赛真题解析
  • string类型
  • Spring IoC 模块设计文档
  • libiec61850 mms协议异步模式
  • 如何构建船舵舵角和船的航向之间的动力学方程?它是一个一阶惯性环节吗?
  • 抖音怎么下载视频
  • 好未来0520上机考试题1:括号的最大嵌入深度
  • 零基础入门PCB设计 强化篇 第六章(实验——USB拓展坞PCB绘制)
  • Spring注解原理深度解析:从入门到精通
  • 免费 SecureCRT8.3下载、安装、注册、使用与设置
  • c++11线程安全
  • 图片批量格式转换工具
  • pcie 日常问答0604
  • 第一章 无刷电机(BLDC)基础知识
  • 缓冲区溢出
  • 【web笔记】JavaScript实现有动画效果的进度条
  • opencascade 小技巧截取两点间的曲线
  • iview中的table组件点击一行中的任意一点选中本行
  • 第5章:Cypher查询语言进阶