显示线框和纯色

Posted

技术标签:

【中文标题】显示线框和纯色【英文标题】:Display wireframe and solid color 【发布时间】:2015-10-10 21:52:51 【问题描述】:

是否可以在同一对象上显示对象的线框以及其面的纯色?我找到了一种使用对象克隆并分配不同材料的方法,例如

var geometry = new THREE.PlaneGeometry(plane.width, plane.height,width - 1, height - 1);
var materialWireframe = new THREE.MeshPhongMaterial(color:"red",wireframe:true);
var materialSolid = new THREE.MeshPhongMaterial(color:"green",wireframe:false);
var plane = new THREE.Mesh(geometry, materialWireframe );
var plane1 = plane.clone();
plane1.material = materialSolid ;
plane1.material.needsUpdate = true;

有什么想法吗?

【问题讨论】:

也许是自定义着色器? 你能进一步解释一下吗?有人如何为此目的使用着色器材质? 您可以定义自己的着色器,因此您可以尝试:aerotwist.com/tutorials/an-introduction-to-shaders-part-1 如果没有,您始终可以使用具有纯色背景的线框纹理。 看看:threejs.org/examples/#webgl_materials_wireframe 【参考方案1】:

要同时渲染模型及其线框,您可以使用如下模式:

// mesh
var material = new THREE.MeshPhongMaterial( 
    color: 0xff0000,
    polygonOffset: true,
    polygonOffsetFactor: 1, // positive value pushes polygon further away
    polygonOffsetUnits: 1
 );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh )

// wireframe
var geo = new THREE.EdgesGeometry( mesh.geometry ); // or WireframeGeometry
var mat = new THREE.LineBasicMaterial(  color: 0xffffff  );
var wireframe = new THREE.LineSegments( geo, mat );
mesh.add( wireframe );

polygonOffset 的使用将有助于防止网格材料和线框线之间的 z-fighting。因此,线框看起来会好很多。

three.js r.126

【讨论】:

linewidth 不会使用 EdgesHelper 或 WireframeHelper 更改线条的宽度 @Marcs 如果您运行的是 Windows,则可能是角度限制。 是的,刚刚在 linux 上测试过,并且 linewidth 属性有效。不过有点烦人。 如果网格几何形状发生变化,此解决方案不起作用。 这需要额外的 GPU 调用来添加线框。如果材质着色器在一种材质中支持所有这些,那就太好了。【参考方案2】:

为此,一种可能性是使用 GLSL 片段着色器,当片段靠近三角形的一个边缘时,它会改变片段颜色。这是我正在使用的 GLSL 着色器。作为输入,它采用三角形中片段的重心坐标,以及为每个边缘选择是否应该绘制的边缘掩码。 (rem:出于向后兼容性的原因,我不得不将它与兼容性配置文件一起使用,如果你不想这样做,它可以很容易地适应):

(片段来源)

#version 150 compatibility

flat in float diffuse;
flat in float specular;
flat in vec3  edge_mask;
in vec2 bary;
uniform float mesh_width = 1.0;
uniform vec3 mesh_color = vec3(0.0, 0.0, 0.0);
uniform bool lighting = true;
out vec4 frag_color;

float edge_factor()
    vec3 bary3 = vec3(bary.x, bary.y, 1.0-bary.x-bary.y);
    vec3 d = fwidth(bary3);
    vec3 a3 = smoothstep(vec3(0.0,0.0,0.0), d*mesh_width, bary3);
    a3 = vec3(1.0, 1.0, 1.0) - edge_mask + edge_mask*a3;
    return min(min(a3.x, a3.y), a3.z);


void main() 
    float s = (lighting && gl_FrontFacing) ? 1.0 : -1.0;
    vec4  Kdiff = gl_FrontFacing ?
         gl_FrontMaterial.diffuse : gl_BackMaterial.diffuse;
    float sdiffuse = s * diffuse;
    vec4 result = vec4(0.1, 0.1, 0.1, 1.0);
    if(sdiffuse > 0.0) 
       result += sdiffuse*Kdiff +
                 specular*gl_FrontMaterial.specular;
    
    frag_color = (mesh_width != 0.0) ?
                  mix(vec4(mesh_color,1.0),result,edge_factor()) :
                  result;

【讨论】:

使用更高版本的 TS 可以使用 this.fragmentSrc = ` 语法,它允许多行字符串。 网上有使用这个的例子吗? 这里有一个在线示例:homepages.loria.fr/BLevy/GEOGRAM/geobox.html 我正在尝试使用 Autodesk 的查看器来实现这一点,但它不起作用,我在这里问过这个问题:***.com/questions/45917611/… 任何想法为什么?【参考方案3】:

为了避免克隆我的对象,我使用了这样的模式:

var mat_wireframe = new THREE.MeshBasicMaterial(color: 0x000000, wireframe: true);
var mat_lambert = new THREE.MeshLambertMaterial(color: 0xffffff, shading: THREE.FlatShading);
var meshmaterials = [ mat_wireframe, mat_lambert ];

然后像这样将它应用到我的网格中:

var myMesh = THREE.SceneUtils.createMultiMaterialObject( mesh_geometry, meshmaterials );
scene.add( myMesh ) ; 

希望对你有帮助……

【讨论】:

createMultiMaterialObject() 为每种材料实例化一个单独的Mesh,因此不会“避免克隆”。【参考方案4】:

这也可以通过 WireframeGeometry 来实现: https://threejs.org/docs/#api/en/geometries/WireframeGeometry。 (并给平面和线相同的位置,您也可以使用不透明度查看文档)。

let geometryWithFillAndWireFrame = () => 

    let geometry = new THREE.PlaneGeometry(250, 250, 10, 10);
    let material = new THREE.MeshBasicMaterial(  color: 0xd3d3d3 );
    let plane = new THREE.Mesh(geometry, material);

    scene.add(plane);

    let wireframe = new THREE.WireframeGeometry( geometry );

    let line = new THREE.LineSegments( wireframe );
        
    line.material.color.setHex(0x000000);
        
    scene.add(line);
        
;

【讨论】:

以上是关于显示线框和纯色的主要内容,如果未能解决你的问题,请参考以下文章

将纹理应用到线框

场景视图控制栏

osg 线框模式,点模式切换

编写一个Applet小程序,显示一个文本框和一个按钮,单击按钮,在文本框内显示当前时间。

3dmax线框颜色怎么用?我的是vr3.2。2015的软件。谢谢。

DirectX11 非实体线框