当前位置:   article > 正文

threejs-生成带宽度的线-MeshLine的使用

meshline

线材质设置linewidth无效的原因

由于OpenGL Core Profile与 大多数平台上WebGL渲染器的限制,无论如何设置该值,线宽始终为1。 解决方法:线用面来代替,首选使用现成的库,今天就使用MeshLine.js

MeshLine.js介绍

引入

原版github.com/spite/THREE…
es版代码地址,使用这一版 github.com/utsuboco/TH…

  1. npm i three.meshline
  2. 复制代码
  1. import { MeshLine, MeshLineMaterial, MeshLineRaycast } from 'meshline';
  2. 复制代码

介绍

1.MeshLine主要方法

setPoints

  1. setPoints(points: Float32Array | Array<number>, wcb?: (p: number) => any): void;
  2. 复制代码

根据传入的顶点数据生成几何体

setGeometry

  1. setGeometry(g: THREE.BufferGeometry, c: (p: number) => any): void;
  2. 复制代码

根据一个THREE.BufferGeometry来获取顶点数据生成几何体

2.MeshLineMaterial主要属性介绍

MeshLineMaterial继承自ShaderMaterial,所以ShaderMateria上的有些属性也是可以用的(比如 wireframe: true)

  1. export class MeshLineMaterial extends THREE.ShaderMaterial
  2. 复制代码
  • map - 贴图 THREE.Texture
  • useMap - 是否使用贴图 (0 - 不使用,用color中的颜色, 1 - 使用)
  • alphaMap - 一张灰度纹理,用于控制整个表面的不透明度 THREE.Texture
  • useAlphaMap - 是否使用灰度贴图 (0-不使用, 1-使用)
  • repeat - 设置纹理的重复 THREE.Vector2
  • color - 线的颜色
  • opacity - 透明度 (transparent 需要透明设置为 true`)
  • alphaTest - 透明度测试,设置一个0-1的值,透明度小于这值的就不会显示
  • dashArray - 通俗解释为 一组虚线(有颜色部分跟间隔部分加起来)占总长度的比例,决定绘制多少组虚线(详见后面示例)
  • dashOffset - 一组虚线中间隔开始的位置,改变其位置用来实现动画 (详见后面示例)
  • dashRatio - 定义一组虚线中无颜色的间隔部分占比为多少 0-1(详见后面示例)
  • resolution - 指定画布大小THREE.Vector2 
  • sizeAttenuation - 线的大小是否会受相机影响。(0 - 不会, 1 - 会)
  • lineWidth - 线宽

3.MeshLineRaycast使线可以被选中

  1. mesh.raycast = MeshLineRaycast
  2. 复制代码

把线模型这样设置后,raycaster.intersectObjects([线模型])的时候,就能捕捉到线模型了

简单使用

开启wireframe: true,看出生成的几何体,是跟着相机在不断调整朝向,才看起来不是一个片 

  1. ....省去基本场景的搭建
  2. // 生成一段贝赛尔曲线
  3. const curve = new THREE.CubicBezierCurve3(
  4. new THREE.Vector3(-100, 0, 0),
  5. new THREE.Vector3(-50, 150, 0),
  6. new THREE.Vector3(200, 150, 0),
  7. new THREE.Vector3(100, 0, 0)
  8. )
  9. // 获取这段线上51个坐标点
  10. const points = curve.getPoints(50)
  11. // 将坐标数据存入positions中
  12. const positions = []
  13. for (let j = 0; j < points.length; j++) {
  14. positions.push(points[j].x, points[j].y, points[j].z)
  15. }
  16. // 初始化MeshLine
  17. const line = new MeshLine()
  18. // 传入顶点坐标数据
  19. line.setPoints(positions)
  20. // 获取纹理,官方案例中的纹理
  21. this.texture = new THREE.TextureLoader().load('static/material/stroke.png')
  22. this.texture.wrapS = this.texture.wrapT = THREE.RepeatWrapping
  23. // 生成线材质
  24. this.material = new MeshLineMaterial({
  25. useMap: 0,
  26. color: new THREE.Color(0x006666),
  27. opacity: 1,
  28. resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
  29. sizeAttenuation: 1,
  30. lineWidth: 20,
  31. transparent: true,
  32. wireframe: true,
  33. map: this.texture
  34. })
  35. // 生成模型
  36. const mesh = new THREE.Mesh(line.geometry, this.material)
  37. this.scene.add(mesh)
  38. 复制代码

参数调整

1.使用纹理

  1. this.material = new MeshLineMaterial({
  2. useMap: 1, //修改
  3. color: new THREE.Color(0x006666),
  4. opacity: 1,
  5. resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
  6. sizeAttenuation: 1,
  7. lineWidth: 20,
  8. transparent: true,
  9. // wireframe: true, //修改
  10. map: this.texture
  11. })
  12. 复制代码

2.调整repeat跟间隔相关

为了直观注释掉transparent: true

  1. this.material = new MeshLineMaterial({
  2. useMap: 1,
  3. color: new THREE.Color(0x006666),
  4. opacity: 1,
  5. resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
  6. sizeAttenuation: 1,
  7. lineWidth: 20,
  8. // transparent: true, // 修改
  9. // wireframe: true,
  10. dashArray: 0.5, // 修改
  11. dashRatio: 0.1, // 新增
  12. repeat: new THREE.Vector2(2, 1), // 新增
  13. map: this.texture
  14. })
  15. 复制代码

dashArray: 0.5,就是每组占0.5,所以分成了两组

repeat: new THREE.Vector2(2, 1),纹理x重复为2,就平铺为两个

dashRatio: 0.1,每组中,间隔部分占比为0.1

3.修改dashOffset动起来

  1. this.material = new MeshLineMaterial({
  2. useMap: 0, // 修改
  3. color: new THREE.Color(0x006666),
  4. opacity: 1,
  5. resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
  6. sizeAttenuation: 1,
  7. lineWidth: 20,
  8. transparent: true,
  9. // useDash: 1,
  10. // wireframe: true,
  11. dashArray: 0.5,
  12. dashRatio: 0.1,
  13. dashOffset: 0, // 新增
  14. repeat: new THREE.Vector2(2, 1),
  15. map: this.texture
  16. })
  17. 复制代码

动态改变dashOffset

  1. // 渲染
  2. _animate() {
  3. requestAnimationFrame(this._animate.bind(this))
  4. if (this.material) {
  5. this.material.uniforms.dashOffset.value -= 0.005
  6. }
  7. }
  8. 复制代码

不使用纹理时 

 useMap改为1,使用纹理时 

问题来了来,纯色时看着正常,换为纹理时,看得出dashOffset修改的是间隔的位置,纹理的uv并没有动,要想uv动,需要修改源码

4.uv动起来,修改源码,增加参数

参考大佬的修改方式 github.com/maptalks/ma… 下载meshline源码,在源码src中找到material.js,学习上面的方式修改,加入offset参数相关代码,使纹理位置可以改变
( 修改完后可以build出meshline.es.js来使用,或者不压缩直接把meshline文件夹下的文件都放入项目中使用)

 同步改变间隔跟新增的offset参数,问题解决

  1. // 渲染
  2. _animate() {
  3. requestAnimationFrame(this._animate.bind(this))
  4. if (this.material) {
  5. this.material.uniforms.offset.value.x -= 0.005
  6. this.material.uniforms.dashOffset.value -= 0.005
  7. }
  8. }
  9. 复制代码

5.用几何模型来设置顶点

  1. // 用一个正方体来生成线
  2. const geometry = new THREE.BoxGeometry(100, 100, 100)
  3. line.setGeometry(geometry)
  4. 复制代码

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/96120
推荐阅读
相关标签
  

闽ICP备14008679号