Better

Ethan的博客,欢迎访问交流

关于 three.js 的一些小知识

一些使用 three.js 过程中总结的小知识,以及一些使用建议,建议绝大部分来自看到的一篇文章,因此没有实践过,不保证有效哈。

Raycaster

Raycaster 是对 Ray 的进一步封装,用于管理好 ray.origin 和 ray.direction。本质上是对 Object3D.raycast 方法的调用,Object3D 中只定义了空方法,具体交给 Mesh、Line 以及 Points 去实现。

Line 对 raycast 的实现

  • raycaster.params.Line.threshold 设置的是世界坐标参数,并不是屏幕坐标
  • 通过调用 ray.intersectsSphere 先判断包容球是否相交,不相交直接返回空,提升性能,相交则继续
  • 对线段进行打断,通过 ray.distanceSqToSegment 获取距离的平方,因为开方比较耗时,所以通过平方进行判断,如果超过具体,则返回,在容忍值内则继续
  • 封装 Intersection 对象进行返回

Points 对 raycast 的实现

  • 先判断包容球是否相交
  • 调用 ray.distanceSqToPoint 依次获取距离平方,在容忍值内则继续
  • 通过 ray.closestPointToPoint 获得该点距离射线最近的点
  • 封装 Intersection 对象进行返回

Mesh 对 raycast 实现

  • 根本没用到 threshold 参数,哈哈
  • 先通过 ray.intersectsSphere 判断包容球
  • 再通过 ray.intersectsBox 判断包容盒
  • Mesh 对于判断具体的相交逻辑,会更复杂一些,关键函数 checkIntersection
    • 获取三角形顶点,通过 ray.intersectTriangle 进行判断

Intersection 属性解释

  • distance
  • face:是哪个片面相交了,有时候有用,比如给该片面添加边框
  • faceIndex:片面索引
  • object:具体对象
  • point:相交点世界坐标

像素大小

像素大小?世界大小

  • Line 的 linewidth 属性,由于渲染器的限制,始终保持 1
  • Points 可通过的 size 设置大小,且提供 sizeAttenuation 属性设置是否响应缩放,但仅限透视相机,反言之,正交相机永远保持特定像素大小,这恰恰是有些场景需要的

不同 Line 的区别

three.js 官方对于 Line 有三种实现

  • Line:底层使用 gl.LINE_STRIP,如果首尾相接,使用该种方式,n+1 个点绘制 n 条线段
  • LineLoop:底层使用 gl.LINE_LOOP,相比 LINE_STRIP 而言,首尾会自动闭合
  • LineSegments:底层使用 gl.LINES,根据一根根线段进行绘制,比如两条线就需要 4 个点,即使线段首尾相连

关于 Points 实现

three.js 本身是内置对于 Points 对象,但只能通过方块的方式,但我们设计都喜欢圆形风格,实现圆形有两种方案

  • 使用 Mesh 搭配 CircleGeometry 实现,非常不推荐
  • 使用 Points,应用一个圆形贴图,推荐这种,性能更好,具体参考webgl_interactive_points

关于颜色

three.js 对于有颜色的渲染是不准确的,如果对于颜色要求比较高,可以尝试如下设置

  • 渲染器:renderer.gammaFactor = 2.2; renderer.outputEncoding = THREE.sRGBEncoding;
  • 颜色:color.convertSRGBToLinear();
  • 材质:colorMap.encoding = sRGBEncoding;

资料



留言