8

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

但事情就是这样。

加载对象后,我想在其上应用另一个纹理。这是因为第一纹理代表物体的表面材料。第二个纹理是一张图纸,我想将其放置在模型上的特定位置。

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

我看到 three.js 创建了一个 的实例THREE.Object3D,并且该实例具有“子”数组和一个THREE.Mesh.

当我尝试将纹理应用到该网格 ( mesh.material.map = texture) 时,我会丢失初始纹理。

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

我也尝试过使用new THREE.MeshFaceMaterial( materials )(如this answer中所建议)但没有成功。

更新

我尝试了@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将一个纹理应用到另一个纹理上。我看到了一些使用一种纹理的示例,但仍然不确定如何以重叠状态显示两者。我也不确定如何将纹理放置在网格上的特定位置。

4

2 回答 2

19

你有几个选择:

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

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

    THREE.SceneUtils.createMultiMaterialObject( geometry, materials );

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

ShaderMaterial这是实现混合两种纹理的最简单的three.js 示例: https ://jsfiddle.net/6bg4qdhx/3/ 。


编辑:另请参阅Is there a built-in way to layer textures within the standard PBR shader?

三.js r.92

于 2013-05-27T22:46:49.287 回答
4

您加载的对象具有几何体(以及它的顶点、面和 UV)和材质。创建以某种适合您的方式组合纹理的 ShaderMaterial,并使用加载对象的几何体创建网格。

使用 ShaderMaterial 并将两个纹理设置为制服,然后在着色器中混合它们。

所以,你制作 ShaderMaterial:

var vertShader = document.getElementById('vertex_shh').innerHTML;
var fragShader = document.getElementById('fragment_shh').innerHTML;

var attributes = {}; // custom attributes

var uniforms = {    // custom uniforms (your textures)

  tOne: { type: "t", value: THREE.ImageUtils.loadTexture( "cover.png" ) },
  tSec: { type: "t", value: THREE.ImageUtils.loadTexture( "grass.jpg" ) }

};

var material_shh = new THREE.ShaderMaterial({

  uniforms: uniforms,
  attributes: attributes,
  vertexShader: vertShader,
  fragmentShader: fragShader

});

并使用该材料创建网格:

var me = new THREE.Mesh( my_loaded_model, material_shh ); // you previously loaded geometry of the object

您可以放置​​最简单的顶点着色器:

varying vec2 vUv;

void main()
{
    vUv = uv;
    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    gl_Position = projectionMatrix * mvPosition;
}

和片段着色器将实际进行混合:

#ifdef GL_ES
precision highp float;
#endif

uniform sampler2D tOne;
uniform sampler2D tSec;

varying vec2 vUv;

void main(void)
{
    vec3 c;
    vec4 Ca = texture2D(tOne, vUv);
    vec4 Cb = texture2D(tSec, vUv);
    c = Ca.rgb * Ca.a + Cb.rgb * Cb.a * (1.0 - Ca.a);  // blending equation or wahtever suits you
    gl_FragColor= vec4(c, 1.0);
}
于 2013-05-31T11:39:39.153 回答