web-dev-qa-db-ja.com

ワイヤーフレームと単色を表示する

同じオブジェクト上にオブジェクトのワイヤーフレームとその面の無地を表示することは可能ですか?オブジェクトのクローンを使用してさまざまなマテリアルを割り当てる方法を見つけました。

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;

何かご意見は?

17
prieston

モデルとそのワイヤーフレームの両方をレンダリングするには、次のようなパターンを使用できます。

// 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, linewidth: 2 } );
var wireframe = new THREE.LineSegments( geo, mat );
mesh.add( wireframe );

polygonOffsetを使用すると、メッシュマテリアルとワイヤーフレームライン間のzファイティングを防ぐことができます。その結果、ワイヤーフレームはずっと良く見えます。

フィドル: http://jsfiddle.net/tfjvggfu/24/

編集:three.js r.82に更新されました

43
WestLangley

これは、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);

};
2

そのためには、GLSLフラグメントシェーダーを使用して、フラグメントが三角形の1つのエッジに近いときにフラグメントの色を変更することができます。これが私が使用している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;
}
2
BrunoLevy

オブジェクトのクローンを回避するために、次のようなパターンを使用しました。

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 ) ; 

それが役に立てば幸いです...

2
Julien_