问题描述
我有一个模型的.obj和.mtl文件,我通过 OBJMTLLoader
加载它。 .mtl指定要应用于模型的纹理,并且three.js加载模型并使用应用的纹理渲染它就好了。
但这就是事情。
加载一个对象后,我想在其上应用另一个纹理。这是因为第一纹理表示对象的表面材质。第二个纹理是一个绘图,我想定位在模型的特定位置。
我的问题是:如何应用第二个纹理到已经加载(和纹理化)的对象?
我看到three.js创建了一个 THREE.Object3D $的实例c $ c>,并且该实例具有children数组,其中一个实例为
THREE.Mesh
。
我尝试将纹理应用于该网格( mesh.material.map = texture
),我失去了初始纹理。
我查看了这个但没有找到答案。
我还尝试使用新的THREE.MeshFaceMaterial(材料)
(如)但未成功。
更新:
我做了这个简单的演示,改编了来自three.js OBJLoader -
我正在使用 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
将一个纹理应用到另一个纹理上。我看到一些但仍然不确定如何在覆盖状态。我也不确定如何在网格上的特定位置定位纹理。
您有多种选择:
-
您可以使用画布工具在javascript端混合图像,并使用单个纹理贴图创建单个材质。
-
您可以从单个几何体和材质数组创建多材质对象。 (这种方法只创建了多个相同的网格,每个网格都有一种材质,通常在其中一种材质为线框时使用。如果一种材质是透明的,它也可以正常工作。)
THREE.SceneUtils.createMultiMaterialObject(几何,材料);
-
你可以实现具有自定义
ShaderMaterial
的多纹理效果。有两个纹理输入,并在着色器中实现颜色混合。
这里有一个最简单的三个示例。 js ShaderMaterial
可能实现两种纹理的混合:。
编辑:另见
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:
You can mix the images on the javascript side using canvas tools, and create a single material with a single texture map.
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 );
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多个材质的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!