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

时间:2021-08-16 04:53:22

I am trying to add a phong material to my .obj model along with a shader Area light, However i tried to use Meshface material using array to load both materials but the model completely disappears when i do so.

我试图添加一个phong材料到我的.obj模型以及一个着色器区域灯,但是我试图使用Meshface材料使用数组加载两种材料,但模型完全消失了,当我这样做。

The scenario works when i use either of them but not both together, is there anyway to overcome this issue ?

当我使用它们中的任何一个但不能同时使用时,该方案是有效的,无论如何都要克服这个问题吗?

Here is the 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);

}

The main issue section

主要问题部分

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

Area light reference:http://jsfiddle.net/hh74z2ft/1/

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

Expected result is similar to this image that even the chandelier should be illuminated like torusknot along with phongness [no phongness in this image ] [.obj模型上的Phong材料没有对three.js中的区域光做出反应]2

预期结果与此图像类似,即使枝形吊灯也应像torusknot一样照亮phongness [此图像中没有phongness] [] 2

1 个解决方案

#1


0  

Unfortunately, if I understood you correctly, this will not work.

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

A material (among other things) defines how a given fragment of a triangle will be shaded. There can always be only one material for any given triangle. The face-material is for handling the case where you want to render different faces with different materials, but it's still just one material per triangle.

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

There is a concept in three.js named multiMaterial (have a look at THREE.SceneUtils.createMultiMaterialObject()). But that will simply create multiple meshes with the same geometry and different materials, so every triangle will get rendered twice, once with every material.

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

Now the Problem is that the AreaLight implementation has it's very own concept of how the light is represented (via shader-uniforms), and that is completely different from how the phong-material works. So, even if you did somehow add a phong-material to the object to get the specular reflections, the phong-material wouldn't know how to deal with the area-light source (it wouldn't even know that there is any light in the scene).

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

In order to get the behaviour you like to see you would need to add a specular term (the calculation-formula for specular reflections of the surface) to the fragment-shader and maybe some uniforms to control it's behaviour. This is a really complicated thing to do, especially for area-lights (if it were easy, we'd already have it in three.js).

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

However, there is some work being done based on latest research in that field, you might want to have a look at this issue and the demo here. There is also a pull-request for this here.

但是,根据该领域的最新研究,有一些工作正在进行中,您可能希望在此处查看此问题和演示。这里还有一个拉动请求。

#1


0  

Unfortunately, if I understood you correctly, this will not work.

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

A material (among other things) defines how a given fragment of a triangle will be shaded. There can always be only one material for any given triangle. The face-material is for handling the case where you want to render different faces with different materials, but it's still just one material per triangle.

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

There is a concept in three.js named multiMaterial (have a look at THREE.SceneUtils.createMultiMaterialObject()). But that will simply create multiple meshes with the same geometry and different materials, so every triangle will get rendered twice, once with every material.

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

Now the Problem is that the AreaLight implementation has it's very own concept of how the light is represented (via shader-uniforms), and that is completely different from how the phong-material works. So, even if you did somehow add a phong-material to the object to get the specular reflections, the phong-material wouldn't know how to deal with the area-light source (it wouldn't even know that there is any light in the scene).

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

In order to get the behaviour you like to see you would need to add a specular term (the calculation-formula for specular reflections of the surface) to the fragment-shader and maybe some uniforms to control it's behaviour. This is a really complicated thing to do, especially for area-lights (if it were easy, we'd already have it in three.js).

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

However, there is some work being done based on latest research in that field, you might want to have a look at this issue and the demo here. There is also a pull-request for this here.

但是,根据该领域的最新研究,有一些工作正在进行中,您可能希望在此处查看此问题和演示。这里还有一个拉动请求。