通过OBJMTLLoader加载对象的三个.js多个材质 [英] Three.js multiple materials on object loaded via OBJMTLLoader

查看:332
本文介绍了通过OBJMTLLoader加载对象的三个.js多个材质的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模型的.obj和.mtl文件,我通过 OBJMTLLoader 加载它。 .mtl指定要应用于模型的纹理,并且three.js加载模型并使用应用的纹理渲染它就好了。



但这就是事情。



加载一个对象后,我想在其上应用另一个纹理。这是因为第一纹理表示对象的表面材质。第二个纹理是一个绘图,我想定位在模型的特定位置。



我的问题是:如何应用第二个纹理到已经加载(和纹理化)的对象



我看到three.js创建了一个 THREE.Object3D ,并且该实例具有children数组,其中一个实例为 THREE.Mesh



我尝试将纹理应用于该网格( mesh.material.map = texture ),我失去了初始纹理。



我查看了这个关于应用多个纹理和JSONLoader的问题但没有找到答案。



我还尝试使用新的THREE.MeshFaceMaterial(材料)(如此答案)但未成功。



更新



<我尝试了@WestLangley建议使用多材质对象,但仍然无法在另一个上面渲染一种材料。



我做了这个简单的演示,改编了来自three.js OBJLoader - http://dl.dropboxusercontent.com/u/ 822184 / webgl_multiple_texture / index.html



我正在使用 THREE.SceneUtils.createMultiMaterialObject ,传递克隆从.obj加载的主要网格的几何。我也给它2个纹理 - 一个用于整个表面,另一个用于模型的前表面。



但是这不起作用。我添加了2个复选框,用于切换相应材料的可见属性。您可以看到材料存在,但我看不到第二个下面的第一个。



加载/渲染的关键如下:

  var texture = THREE.ImageUtils.loadTexture('fabric.jpg'); 
var texture2 = THREE.ImageUtils.loadTexture('table.jpg');

texture2.offset.set(-0.65,-2.5);
texture2.repeat.set(4,4);

var loader = new THREE.OBJLoader();
loader.addEventListener('load',function(event){

var mainMesh = event.content.children [0] .children [0];

multiMaterialObject = THREE.SceneUtils.createMultiMaterialObject(
mainMesh.geometry.clone(),[
new THREE.MeshLambertMaterial({map:texture2}),
new THREE.MeshLambertMaterial({map:texture })
]);

multiMaterialObject.position.y = -80;
scene.add(multiMaterialObject);
});

loader.load('male02.obj');

更新#2



此时,我认为最好的办法是使用 THREE.ShaderMaterial 将一个纹理应用到另一个纹理上。我看到一些使用一个纹理的示例但仍然不确定如何在覆盖状态。我也不确定如何在网格上的特定位置定位纹理。

解决方案

您有多种选择:


  1. 您可以使用画布工具在javascript端混合图像,并使用单个纹理贴图创建单个材质。


  2. 您可以从单个几何体和材质数组创建多材质对象。 (这种方法只创建了多个相同的网格,每个网格都有一种材质,通常在其中一种材质为线框时使用。如果一种材质是透明的,它也可以正常工作。)



    THREE.SceneUtils.createMultiMaterialObject(几何,材料);


  3. 你可以实现具有自定义 ShaderMaterial 的多纹理效果。有两个纹理输入,并在着色器中实现颜色混合。


这里有一个最简单的三个示例。 js ShaderMaterial 可能实现两种纹理的混合: https: //jsfiddle.net/6bg4qdhx/3/






编辑:另见是否有内置的在标准PBR着色器中对图层进行分层?



three.js r.92


I have ".obj" and ".mtl" files of a model and I'm loading it via OBJMTLLoader. ".mtl" specifies texture to apply to a model, and three.js loads model and renders it with applied texture just fine.

But here's the thing.

Once an object is loaded, I would like to apply another texture onto it. This is because first texture represents surface material of an object. And second texture is a drawing, that I'd like to position at a specific location on a model.

My question is: how to apply a second texture onto already loaded (and texturized) object?

I see that three.js creates an instance of THREE.Object3D, and that instance has "children" array with one instance of THREE.Mesh.

When I try to apply a texture to that mesh (mesh.material.map = texture), I lose initial texture.

I looked into this question about applying multiple textures and JSONLoader but didn't find an answer.

I also tried using new THREE.MeshFaceMaterial( materials ) (as suggested in this answer) but unsuccessfully.

UPDATE:

I tried @WestLangley's suggestion to use multi-material object, but am still unable to render one material on top of another one.

I made this simple demo, adapted from three.js OBJLoader — http://dl.dropboxusercontent.com/u/822184/webgl_multiple_texture/index.html

I'm using THREE.SceneUtils.createMultiMaterialObject as suggested, passing it cloned geometry of main mesh loaded from .obj. I'm also giving it 2 textures — one for entire surface, another one — for front surface of the model.

But this doesn't work. I added 2 checkboxes that toggle "visible" property of corresponding materials. You can see that materials are present, but I can't see the first one from beneath second one.

The crux of the loading/rendering is as follows:

var texture = THREE.ImageUtils.loadTexture('fabric.jpg');
var texture2 = THREE.ImageUtils.loadTexture('table.jpg');

texture2.offset.set(-0.65, -2.5);
texture2.repeat.set(4, 4);

var loader = new THREE.OBJLoader();
loader.addEventListener( 'load', function ( event ) {

  var mainMesh = event.content.children[0].children[0];

  multiMaterialObject = THREE.SceneUtils.createMultiMaterialObject( 
    mainMesh.geometry.clone(), [
      new THREE.MeshLambertMaterial({ map: texture2 }),
      new THREE.MeshLambertMaterial({ map: texture })
    ]);

  multiMaterialObject.position.y = -80;
  scene.add(multiMaterialObject);
});

loader.load( 'male02.obj' );

UPDATE #2

At this point, I think the best bet is to use THREE.ShaderMaterial to apply one texture onto another. I see some examples of using one texture but still unsure how to display both in overlaid state. I'm also not sure how to position texture at a specific location on a mesh.

解决方案

You have several choices:

  1. You can mix the images on the javascript side using canvas tools, and create a single material with a single texture map.

  2. You can create a multi-material object from a single geometry and an array of materials. (This approach just creates multiple identical meshes, each with one of the materials, and usually is used when one of the materials is wireframe. It may also work OK if one material is transparent.)

    THREE.SceneUtils.createMultiMaterialObject( geometry, materials );

  3. You can achieve a multi-texture effect with a custom ShaderMaterial. Have two texture inputs, and implement color mixing in the shader.

Here an example of just about the simplest three.js ShaderMaterial possible that implements mixing of two textures: https://jsfiddle.net/6bg4qdhx/3/.


EDIT: Also see Is there a built-in way to layer textures within the standard PBR shader?

three.js r.92

这篇关于通过OBJMTLLoader加载对象的三个.js多个材质的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆