Threejs中设置Line的宽

今天在做Threejs绘制线条时,绘制了一个圆,但是由于线条太细,为了给线条加粗,在LineBasicMaterial中添加了linewidth属性,但是发现并没有效果,代码如下:

 const curve = new THREE.EllipseCurve(
          0, 0,  // 椭圆中心x,y坐标
          5, 5,  // 椭圆长半轴和短半轴
          0, 2 * Math.PI  // 起始角度和结束角度,设置为0到2π使曲线闭合
      );
      const points = curve.getPoints(50);  // 获取50个点
      const geometry = new THREE.BufferGeometry().setFromPoints(points);
      const material = new THREE.LineBasicMaterial({
        color: '#FF0000',
        linewidth: 8,
      });
      const line = new THREE.Line(geometry, material);
      this.scene.add(line);

但是查找了官方文档后确实是有这个属性的。但是紧接着下一行,由于OpenGL Core Profil

在 Three.js 中实现“线”(Wide Lines),由于 WebGL 对原生支持的线条度有限制,并且无法直接绘制超出限制范围的大度线条,因此我们需要一些技巧来模拟这种效果。 以下是几种常见的方式来实现线: --- ### **1. 使用 Geometry 或 BufferGeometry 绘制平面** 可以将每条线段视为一个矩形面片 (quad),通过构造几何体并应用材质的方式手动生成加粗后的线段。 ```javascript function createFatLine(vertices, color, thickness) { const geometry = new THREE.BufferGeometry(); // 计算顶点坐标及法向量以构建矩形区域代替传统直线 let positions = []; for(let i=0;i<vertices.length-1;i++) { const pA = vertices[i]; // 当前点 const pB = vertices[i+1]; // 下一节点 var dir = normalize(subtract(pB,pA)); // 方向单位化 var perpDir=[dir[1], -dir[0]]; // 垂直方向 addPoint(positions,[...addVectors(pA,multiplyScalar(perpDir,-thickness/2))]); addPoint(positions,[...addVectors(pA,multiplyScalar(perpDir,+thickness/2))]); addPoint(positions,[...addVectors(pB,multiplyScalar(perpDir,+thickness/2))]); addPoint(positions,[...addVectors(pB,multiplyScalar(perpDir,-thickness/2))]); } function addPoint(array,value){ array.push(value[0],value[1],0); } geometry.setAttribute('position',new Float32BufferAttribute(positions,3)); const material=new THREE.MeshBasicMaterial({color}); return new THREE.Mesh(geometry,material); } ``` 这种方法的优点是可以完全自定义线型、颜色渐变等复杂视觉样式;缺点在于性能上会随着线数增加而下降较快。 --- ### **2. 利用 LineSegments 和 ShaderMaterial 自定义着色器** Three.js 提供了灵活强大的 shader 功能,我们也可以编写 GLSL 着色程序来自行计算像素距离中心的距离,以此为基础渲染出指定度的效果: ```glsl // Vertex Shader 示例代码片段 varying vec4 vColor; void main() { // 调整每个端点位置使得其偏离原始路径形成边界框包围整个目标度范围内的所有内容... } // Fragment Shader 示例代码片段 uniform float uThickness; uniform vec3 uLineColor; void main(){ gl_FragColor = mix(vec4(uBackgroundColor, 1.),vec4(vColor.rgb,vAlpha),smoothstep(0.,uThickness,distanceToCenter)); } ``` 此方法效率较高并且易于维护修改外观属性值如透明度变化规则等。但需要一定的图形学知识才能理解并调试正确的结果呈现形式。 --- ### **3. 直接使用第三方插件库:three-mesh-ui 或 dpr-line-threejs** 如果不想从零开始制作线组件的话,还可以考虑引入现有的开源项目例如 `dpr-line-threejs` 来简化操作步骤同时获得更佳优化过的最终产物质量水平。 安装命令: ```bash npm install dpr-line-threejs --save ``` 简单示例加载流程如下所示: ``` javascript import DPRLine from 'dpr-line-threejs'; const lineMat = new DPRLine.DPRLINE_Material({ color: 0xffffff, linewidth: 5 // 设定所需的实际显示厚度数值大小即可生效响应式适配机制自动完成剩余细节处理工作过程. }); let curvePts=[],lineGeom,lineObj; for(var i=-Math.PI;i<=Math.PI;i+=0.01){curvePts.push(new THREE.Vector3(Math.cos(i)*20, Math.sin(i)*8 ,i*6 ));} lineGeom=DPRLine.createCurveBasedGeometry(curvePts,.07); lineObj=new DPRLine(lineGeom,lineMat); scene.add(lineObj) ``` 这样就可以轻松快速地得到一条具有任意设定尺寸规格特性的三维空间曲线啦! --- **总结来说**, 实现线的关键思路主要是绕过浏览器对 native lines 的局限性约束条件来进行替代方案设计构思活动开展起来。无论是基于 mesh 模拟还是运用高级定制 shaders 技巧都可以达成理想的展示目的需求满足程度标准之上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baker_zhuang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值