2015-07-21 2 views
8

Можно ли отобразить каркас объекта, а также сплошной цвет его граней на одном и том же объекте? Я нашел способ использовать клон объекта и назначить различные материалы, напримерПоказать каркас и сплошной цвет

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; 

любые мысли?

+0

Может быть, пользовательский шейдер? – Shomz

+0

Можете ли вы еще объяснить? Как можно использовать шейдерный материал для этой цели? – mrapsogos

+0

Вы можете определить свои собственные шейдеры, чтобы вы могли попробовать: https://aerotwist.com/tutorials/an-introduction-to-shaders-part-1/ Если нет, вы всегда можете использовать текстуру каркаса с твердым задний план. – Shomz

ответ

21

Оказывать как модель и ее каркас, вы можете использовать шаблон, как это:

// 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 поможет предотвратить г-бой между сетчатым материалом и каркасными линиями. Следовательно, каркас будет выглядеть намного лучше.

скрипку: http://jsfiddle.net/tfjvggfu/24/

EDIT: обновлен до three.js R.82

+0

ширина линии не меняет ширину линий с помощью EdgesHelper или WireframeHelper – Marcs

+1

@Marcs Если вы используете Windows, это, скорее всего, ограничение ANGLE. – WestLangley

+0

Да, только что протестировано на linux и работает свойство linewidth. Однако все это раздражает. – Marcs

2

Чтобы сделать это, возможность заключается в использовании фрагмента GLSL шейдер, который изменяет цвет фрагмента, когда фрагмент находится вблизи одного края треугольника. Вот шейдер GLSL, который я использую. В качестве входных данных он принимает барицентрические координаты фрагмента в треугольнике и краевую маску, которая выбирает для каждого ребра, должна ли она быть нарисована или нет. (Бэр: я должен был использовать его с профилем совместимости для обратной совместимости, если вы не хотите, чтобы сделать это, он может быть легко адаптировано):

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

Используя более поздние версии TS, вы можете использовать синтаксис this.fragmentSrc = ', который позволяет использовать многострочные строки. – Sentinel

+0

Есть ли онлайн-пример, используя это? – shinzou

+0

Это просто ломает форму ... – shinzou

0

Чтобы избежать клонирования моего объекта я использовал рисунок как что:

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

Я надеюсь, что это может помочь ...

+0

'createMultiMaterialObject()' создает экземпляр отдельного 'Mesh' для каждого материала и, следовательно, не« избегает клонирования ». – WestLangley