使用THREE.LineBasicMaterial的线条粗细

时间:2012-07-24 20:35:15

标签: javascript webgl three.js

我正在使用下面的代码在我的three.js场景中创建数百行

edgeGeometry[i] = new THREE.Geometry();
edgeGeometry[i].vertices[0] = v(x1,y1,z1);
edgeGeometry[i].vertices[1] = v(x2,y2,z2);
edgesMat[i] = new THREE.LineBasicMaterial({
    color: 0x6699FF, linewidth: 1, fog:true});
edge[i] = new THREE.Line(edgeGeometry[i], edgesMat[i]);
edge[i].type = THREE.Lines;
scene2.add(edge[i]);

它工作正常,但当我将“linewidth”的值更改为更大或更小的值时,我看到场景中没有区别。
我该如何改变线条的粗细?任何想法?
谢谢,迪米特里斯

9 个答案:

答案 0 :(得分:21)

1)使用原生OpenGL

通过将浏览器设置为使用本机OpenGL而不是ANGLE,可以通过解决方法实现线条粗细的渲染。 You can read here on how to do this on Chrome。 请记住,如果您更换为原生OpenGL,您将遇到性能差异。

修改

主人MrDoob本人posted here how to do this for both Chrome and Firefox

注意: 第一个选项不再是有效的解决方案,因为最新的OpenGL版本也不再支持线宽。检查also @gman his answer。这意味着如果你想使用线条粗细,第二个选项就是你要去的地方。


2)使用THREE.MeshLine class

还有另一种解决方案; this THREE.MeshLine class on github是一个很好的解决方法。它带有一个特殊的THREE.MeshLineMaterial。根据文档,它很简单:

  
      
  • 创建并填充几何
  •   
  • 创建THREE.MeshLine并指定几何
  •   
  • 创建THREE.MeshLineMaterial
  •   
  • 使用THREE.MeshLineTHREE.MeshLineMaterial创建THREE.Mesh
  •   

答案 1 :(得分:18)

您使用的是Windows吗? 我记得这不适用于Windows,因为它没有在ANGLE中实现。

答案 2 :(得分:12)

这种情况发生在Windows Chrome和Firefox中,都使用ANGLE(WebGL到DirectX包装器)。

ANGLE项目仍然没有解决这个问题。你可以在这里解决问题,以获得更高的优先级,并获得通知,如果它将被实施:

https://code.google.com/p/angleproject/issues/detail?id=119

答案 3 :(得分:3)

这已不再是ANGLE中的一个问题,它在所有平台上都是一个问题。浏览器需要切换到OpenGL 4+核心配置文件以支持WebGL2和OpenGL 4+核心配置文件不支持大于1的行宽。从OpenGL 4.0+规范,E.2.1节

  

E.2.1不推荐但仍支持的功能

     

以下功能已弃用,但仍存在于核心配置文件中。它们可能会从未来版本的OpenGL中删除,并在实现核心配置文件的前向兼容上下文中删除。

     
      
  • 宽行 - 大于1.0的LineWidth值将生成INVALID_VALUE错误。
  •   

要绘制较粗的线条,您需要生成几何体。对于three.js,有这个库(Wilt也指出)

https://github.com/spite/THREE.MeshLine

答案 4 :(得分:1)

您可以使用CanvasRenderer而不是Webglrenderer。查看ifficial文档here,其中每个形状的边框线宽= 10;

答案 5 :(得分:1)

您可以使用extrude-polyline为增厚(多边形)线生成simplicial complex并使用three-simplicial-complex将其转换为three.js网格来实现相同的效果:

const THREE = require('three');
const extrudePolyline = require('extrude-polyline');
const Complex = require('three-simplicial-complex')(THREE);

function thickPolyline(points, lineWidth) {
  const simplicialComplex = extrudePolyline({
    // Adjust to taste!
    thickness: lineWidth,
    cap: 'square',  // or 'butt'
    join: 'bevel',  // or 'miter',
    miterLimit: 10,
  }).build(points);

  // Add a z-coordinate.
  for (const position of simplicialComplex.positions) {
    position[2] = 0;
  }

  return Complex(simplicialComplex);
}

const vertices = [[0, 0], [10, 0], [10, 10], [20, 10], [30, 00]];
const geometry = thickPolyline(vertices, 10);

const material = new THREE.MeshBasicMaterial({
  color: 0x009900,
  side: THREE.DoubleSide
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

这是一个complete example以及source。 (目前有一个issue on requirebin阻止它呈现源代码示例。)

如果你想对折线进行纹理贴图,事情会变得复杂一些。

答案 6 :(得分:1)

我使用TubeGeometry在两点之间创建粗线:

查看Helix中的绿线

enter image description here

// line material
var lineMaterial = new THREE.LineBasicMaterial({ color: 0x00ff00 });


let startVector = new THREE.Vector3(
    RADI * Math.cos(t),
    RADI * Math.sin(t),
    3 * t
  );
  let endVector = new THREE.Vector3(
    RADI * Math.cos(t + 10),
    RADI * Math.sin(t + 10),
    3 * t
  );

  let linePoints = [];
  linePoints.push(startVector, endVector);

  // Create Tube Geometry
  var tubeGeometry = new THREE.TubeGeometry(
    new THREE.CatmullRomCurve3(linePoints),
    512,// path segments
    0.5,// THICKNESS
    8, //Roundness of Tube
    false //closed
  );

  //add buffer geometry
  let tubeBufferGeomtry = new THREE.BufferGeometry().fromGeometry(
    tubeGeometry
  );

  let line = new THREE.Line(tubeGeometry, lineMaterial);
  scene.add(line);

答案 7 :(得分:0)

感谢Wilt's answerTHREE.MeshLine指向正确的方向。

这可能比他们想像的要复杂一些,但是...所以这是我非常仔细地遵循他们的文档和demo代码的解决方案...(假设您已经包含了Three和MeshLine ):

    renderer = new THREE.WebGLRenderer({ canvas });

    //...

    function createCircle(resolution) {
        let circleGeometry = new THREE.Geometry();
        for (let rotation = 0; rotation <= Math.PI * 2.0; rotation += Math.PI * 0.1) {
            circleGeometry.vertices.push(
                new THREE.Vector3(Math.cos(rotation), Math.sin(rotation), 0));
        }
        let circleLine = new MeshLine();
        circleLine.setGeometry(circleGeometry);
        //Bonus: parabolic width! (See Z rotation below.)
        //circleLine.setGeometry(circleGeometry, function(point) {
            //return Math.pow(4 * point * (1 - point), 1);
        //});

        //Note: resolution is *required*!
        return new THREE.Mesh(circleLine.geometry,
            new MeshLineMaterial({
                color: 'blue',
                resolution,
                sizeAttenuation: 0,
                lineWidth: 5.0,
                side: THREE.DoubleSide
            }));
    }

    let circle = createCircle(new THREE.Vector2(canvas.width, canvas.height));
    circle.rotation.x = Math.PI * 0.5;
    circle.position.y = 20.0;
    scene.add(circle);

    //In update, to rotate the circle (e.g. if using parabola above):
    world.circle.rotation.z += 0.05;

关闭大小衰减并使用THREE.DoubleSide,就像我在上面所做的那样,无论您从何处看,圆都将看起来像是一个不错的,一致的圆(不是“真实3D”)。

只需一行,您显然可以轻松适应。

答案 8 :(得分:0)

为什么不将不透明度设置为 0.1 之类的? 注意:这仅在您为某物设置边框时才有效,如果它背后没有任何内容,它将无法工作。