2016-08-03 6 views
0

Ich versuche, ein Phonematerial zu meinem .obj-Modell zusammen mit einem Shader Area Licht hinzuzufügen, aber ich habe versucht, Meshface-Material mit Array zu laden Beide Materialien, aber das Modell verschwindet vollständig, wenn ich dies tue.Phong-Material auf einem .obj-Modell reagiert nicht auf Flächenlicht in three.js

Das Szenario funktioniert, wenn ich beide, aber nicht beide zusammen benutze, gibt es trotzdem dieses Problem zu überwinden?

Hier ist die DEMO:

Code:

// area light 
var lightColor = 0xffffff; 
var lightIntensity = 1; 

var geometry = new THREE.PlaneGeometry(100, 50); 

var material = new THREE.MeshBasicMaterial({ 
    color: lightColor, 
    transparent: true, 
    opacity: 0.7, 
    side: THREE.FrontSide 
}); 

areaLight = new THREE.Mesh(geometry, material); 

areaLight.position.set(0, 25, -25); 
areaLight.rotation.set(0, 0, 0); 
areaLight.scale.set(1, 1, 1); 
scene.add(areaLight); 


var Black = new THREE.MeshPhongMaterial({ 
     color: 0x000000, 


    }) 
    // wireframe hack 
areaLight.add(new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ 
    wireframe: true 
}))); 

// areaLight verts 
var vertices = areaLight.geometry.vertices; 
var verts = []; 
verts.push(vertices[0]); 
verts.push(vertices[1]); 
verts.push(vertices[3]); 
verts.push(vertices[2]); 

// uniforms 
var uniforms = { 
    color: { 
     type: "c", 
     value: new THREE.Color(0xaaaadd) 
    }, 

    lightColor: { 
     type: "c", 
     value: areaLight.material.color 
    }, 
    lightIntensity: { 
     type: "f", 
     value: lightIntensity 
    }, 
    lightverts: { 
     type: "v3v", 
     value: verts 
    }, 
    lightMatrixWorld: { 
     type: "m4", 
     value: areaLight.matrixWorld 
    } 
}; 

// attributes 
var attributes = {}; 

// material 
var material = new THREE.ShaderMaterial({ 
    attributes: attributes, 
    uniforms: uniforms, 
    vertexShader: document.getElementById('vertex_shader').textContent, 
    fragmentShader: document.getElementById('fragment_shader').textContent, 
    shading: THREE.SmoothShading 
}); 


var onError = function(xhr) {}; 
THREE.Loader.Handlers.add(/\.dds$/i, new THREE.DDSLoader()); 
var mtl1Loader = new THREE.MTLLoader(); 

mtl1Loader.setBaseUrl('neavik/newmail/'); 
mtl1Loader.setPath('neavik/newmail/'); 
mtl1Loader.load('chandelier.mtl', function(materials) { 

    materials.preload(); 

    var objLoader = new THREE.OBJLoader(); 
    objLoader.setMaterials(materials); 

    objLoader.setPath('neavik/newmail/'); 
    objLoader.load('chandelier.obj', function(object4) { 

     object4.castShadow = true; 
     object4.receiveShadow = true; 
     object4.updateMatrix(); 
     object4.position.set(40, 28, 40); //(0,-5,0.5); 
     object4.scale.x = 0.09; 
     object4.scale.y = 0.05; 
     object4.scale.z = 0.09 



     var mats = []; 
     mats.push(new THREE.MeshPhongMaterial({ 
      color: 0x000000 
     })); 
     mats.push(material); 
     var faceMaterial = new THREE.MeshFaceMaterial(mats); 



     object4.traverse(function(child) { 
      if (child instanceof THREE.Mesh) { 
       if (child.material.name == "chandelier_Outside") { 

        child.material = Black; // When i use faceMaterial here the object disappears 
        child.castShadow = true; 
        child.receiveShadow = true; 
       } 


      } 


     }); 
     scene.add(object4); 
    }); 
}) 

// plane geometry 
var geometry = new THREE.PlaneGeometry(200, 200); 
geometry.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI/2)); 

// plane 
mesh = new THREE.Mesh(geometry, material); 
mesh.position.y = -0.1; 
scene.add(mesh); 

// torus knot 
var geometry = new THREE.TorusKnotGeometry(10, 4, 256, 32, 1, 3, 1); 

// mesh 
mesh = new THREE.Mesh(geometry, material); 
mesh.position.set(0, 28, 0); 
scene.add(mesh); 

} 

Das Hauptproblem Abschnitt

var mats = []; 
     mats.push(new THREE.MeshPhongMaterial({ 
      color: 0x000000 
     })); 
     mats.push(material); 
     var faceMaterial = new THREE.MeshFaceMaterial(mats); 



     object4.traverse(function(child) { 
      if (child instanceof THREE.Mesh) { 
       if (child.material.name == "chandelier_Outside") { 

        child.material = Black; // When i use faceMaterial here the object disappears 
        child.castShadow = true; 
        child.receiveShadow = true; 
       } 


      } 


     }); 
     scene.add(object4); 
    }); 
}) 

Flächenlicht Referenz: zu diesem Bild http://jsfiddle.net/hh74z2ft/1/

Erwartetes Ergebnis ähnlich ist, sogar der Kronleuchter sollte beleuchtet sein ated wie torusknot mit phongness entlang [no phongness in diesem Bild] [enter image description here] 2

+0

was willst du hier? Einige Gesichter dieses Kronleuchters sollten durch das Phong-Material und andere durch das Area-Light-Material beschattet werden. Kannst du vielleicht erklären, was das beabsichtigte Ergebnis wäre? –

+0

@ MartinSchuhfuß Ich wollte nur beide Materialien auf Kronleuchter, so dass es ein phong Material sowie diesen Bereich Licht Shader besitzen kann, habe ich ein Bild aktualisiert, wie es funktioniert, wenn ich nur ein Material verwenden? –

+0

Überprüfen Sie die Objekte Normalen – gaitat

Antwort

0

Leider funktionieren, wenn ich Sie richtig verstanden habe, wird dies nicht.

Ein Material (unter anderem) definiert, wie ein gegebenes Fragment eines Dreiecks schattiert wird. Es kann immer nur ein Material für ein gegebenes Dreieck geben. Das Face-Material ist für den Fall gedacht, dass Sie verschiedene Gesichter mit unterschiedlichen Materialien rendern möchten, aber es ist immer noch nur ein Material pro Dreieck.

Es gibt ein Konzept in three.js namens multiMaterial (siehe THREE.SceneUtils.createMultiMaterialObject()). Aber das wird einfach mehrere Maschen mit der gleichen Geometrie und verschiedenen Materialien erzeugen, so dass jedes Dreieck zweimal gerendert wird, einmal mit jedem Material.

Jetzt ist das Problem, dass die AreaLight-Implementierung ihr eigenes Konzept hat, wie das Licht dargestellt wird (über Shader-Uniformen), und das ist völlig anders als die Funktionsweise des Phong-Materials. Also, selbst wenn Sie dem Objekt irgendwie ein Phong-Material hinzugefügt haben, um die Spiegelreflexionen zu erhalten, würde das Phong-Material nicht wissen, wie es mit der Flächenlichtquelle umgehen soll (es würde nicht einmal wissen, dass es Licht gibt) in der Szene).

Um das gewünschte Verhalten zu erhalten, müssten Sie einen Splitter-Ausdruck (die Berechnungsformel für spiegelnde Reflexionen der Oberfläche) zum Fragment-Shader und eventuell einige Uniformen hinzufügen, um das Verhalten zu steuern. Dies ist eine wirklich komplizierte Sache, besonders für Flächenlichter (wenn es einfach wäre, hätten wir es schon in drei .js).

Es gibt jedoch einige Arbeiten auf der Grundlage der neuesten Forschung in diesem Bereich, können Sie einen Blick auf this issue und die demo here haben. Es gibt auch eine Pull-Anfrage für diese here.