.obj模型上的Phong材料不会对three.js中的区域光做出反应

时间:2016-08-03 04:44:17

标签: javascript three.js

我正在尝试将phong材质添加到我的.obj模型以及着色器区域灯,但是我尝试使用使用数组的Meshface材质来加载两种材质但是当我这样做时模型完全消失。

当我使用其中任何一个但不能同时使用时,情况有效,无论如何都要克服这个问题吗?

以下是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);

}

主要问题部分

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

区域光线参考:http://jsfiddle.net/hh74z2ft/1/

预期的结果与此图像类似,即使是枝形吊灯也应该像torusknot一样照亮phongness [此图片中没有phongness] [enter image description here] 2

1 个答案:

答案 0 :(得分:0)

不幸的是,如果我理解正确,这将无效。

材料(以及其他内容)定义如何将三角形的给定片段着色。对于任何给定的三角形,总是只能有一种材料。面材用于处理您想要使用不同材质渲染不同面的情况,但每个三角形仍然只有一种材质。

在three.js中有一个名为multiMaterial的概念(看看THREE.SceneUtils.createMultiMaterialObject())。但这只会创建具有相同几何和不同材质的多个网格,因此每个三角形都会渲染两次,每种材质都会渲染一次。

现在的问题是,AreaLight实现有它自己如何表示光的概念(通过着色器制服),这与phong材料的工作方式完全不同。因此,即使你以某种方式在物体上添加了一种物质以获得镜面反射,但物质也不知道如何处理区域光源(它甚至不知道场景中有任何光线。)

为了获得您喜欢的行为,您需要将一个镜面术语(表面镜面反射的计算公式)添加到片段着色器中,并且可能需要一些制服来控制它的行为。这是一个非常复杂的事情,特别是对于区域灯(如果它很容易,我们已经在three.js中有它。)

但是,根据该领域的最新研究,有一些工作要做,您可能需要查看this issuedemo here。此here还有一个拉取请求。