2015-07-21 25 views
8

È possibile visualizzare il wireframe dell'oggetto e anche il colore solido dei suoi volti sullo stesso oggetto? Ho trovato un modo utilizzando un clone dell'oggetto e assegnare materiali diversi, ad esempioVisualizzazione wireframe e tinta unita

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; 

qualsiasi idea?

+0

Forse uno shader personalizzato? – Shomz

+0

puoi spiegare ulteriormente? Come può qualcuno usare il materiale shader per questo scopo? – mrapsogos

+0

Puoi definire i tuoi shader, quindi potresti provare con questo: https://aerotwist.com/tutorials/an-introduction-to-shaders-part-1/ In caso contrario, puoi sempre usare una trama wireframe con un solido sfondo. – Shomz

risposta

21

di rendere sia un modello e la sua wireframe, è possibile utilizzare un modello come questo:

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

L'uso di polygonOffset aiuterà a prevenire z-combattimento tra il materiale a rete e la linea wireframe. Di conseguenza, il wireframe apparirà molto meglio.

violino: http://jsfiddle.net/tfjvggfu/24/

EDIT: aggiornato per Three.js r.82

+0

linewidth non modifica la larghezza delle righe con EdgesHelper o WireframeHelper – Marcs

+1

@Marcs Se si utilizza Windows, è probabile che sia presente una limitazione ANGLE. – WestLangley

+0

Sì, appena testato su linux e la proprietà linewidth funziona. Tipo di fastidio però. – Marcs

2

Per fare questo, una possibilità è quella di utilizzare uno shader frammento GLSL che cambia il colore frammento quando il frammento è vicino un bordo del triangolo. Ecco lo shader GLSL che sto usando. Come input, prende le coordinate baricentriche del frammento nel triangolo e una maschera di bordo che seleziona per ogni spigolo se deve essere disegnata o meno. (Rimozione: ho dovuto usare con il profilo di compatibilità per ragioni di compatibilità all'indietro, se non si vuole fare questo, può facilmente essere adattato):

const char* fshader_source = 
     "#version 150 compatibility           \n" 
     "flat in float diffuse;            \n" 
     "flat in float specular;           \n" 
     "flat in vec3 edge_mask;           \n" 
     "in vec2 bary;              \n" 
     "uniform float mesh_width = 1.0 ;         \n" 
     "uniform vec3 mesh_color = vec3(0.0, 0.0, 0.0) ;     \n" 
     "uniform bool lighting = true ;          \n" 
     "out vec4 frag_color ;            \n" 
     "float edge_factor(){            \n" 
     " vec3 bary3 = vec3(bary.x, bary.y, 1.0-bary.x-bary.y) ;   \n" 
     " vec3 d = fwidth(bary3);          \n" 
     " vec3 a3 = smoothstep(vec3(0.0,0.0,0.0), d*mesh_width, bary3); \n" 
     " a3 = vec3(1.0, 1.0, 1.0) - edge_mask + edge_mask*a3;   \n" 
     " return min(min(a3.x, a3.y), a3.z);        \n" 
     "}                 \n" 
     "void main() {              \n" 
     " float s = (lighting && gl_FrontFacing) ? 1.0 : -1.0 ;   \n" 
     " vec4 Kdiff = gl_FrontFacing ?         \n" 
     "   gl_FrontMaterial.diffuse : gl_BackMaterial.diffuse ;  \n" 
     " float sdiffuse = s * diffuse ;         \n" 
     " vec4 result = vec4(0.1, 0.1, 0.1, 1.0);      \n" 
     " if(sdiffuse > 0.0) {           \n" 
     "  result += sdiffuse*Kdiff +         \n" 
     "     specular*gl_FrontMaterial.specular;    \n" 
     " }                \n" 
     " frag_color = (mesh_width != 0.0) ?        \n" 
     "     mix(vec4(mesh_color,1.0),result,edge_factor()) : \n" 
     "     result ;           \n" 
     "}                 \n"; 
+1

Utilizzando le versioni TS successive è possibile utilizzare la sintassi this.fragmentSrc = ', che consente stringhe multilinea. – Sentinel

+0

Esiste un esempio online che utilizza questo? – shinzou

+0

Questo interrompe la forma ... – shinzou

0

Per evitare la clonazione mio oggetto ho usato un modello simile che:

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

e poi applicato alla mia rete così:

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

Spero che potrebbe aiutare ...

+0

'createMultiMaterialObject()' crea un'istanza di 'Mesh' per ogni materiale, e di conseguenza, non" evita la clonazione ". – WestLangley