【问题标题】:threejs - apply materials with texture maps to objects loaded through THREE.ObjectLoaderthreejs - 将带有纹理贴图的材质应用于通过 THREE.ObjectLoader 加载的对象
【发布时间】:2015-04-10 11:23:47
【问题描述】:

我通过 JSON 文件引入几何图形和材质。在大多数情况下,这很好用,除了现在我试图引入纹理贴图。据我所知,THREE.ObjectLoader 会从加载的纹理中去除任何图像信息,因此,材质无法访问图像源。 我尝试了几件事,但它们都导致相同的结果:如果我使用纹理贴图重新创建材质并将其应用于加载的对象,则该对象会消失。

为了确保某些东西可以正常工作,我用一个立方体和一个材质创建了一个简单的场景。这工作得很好:

var textureDiff = THREE.ImageUtils.loadTexture( "img/brick_diffuse.jpg" ); 
textureDiff.wrapS = THREE.RepeatWrapping; 
textureDiff.wrapT = THREE.RepeatWrapping; 
textureDiff.repeat.set( 2, 2 );

var textureBump = THREE.ImageUtils.loadTexture( "img/brick_bump.jpg" ); 
textureBump.wrapS = THREE.RepeatWrapping; 
textureBump.wrapT = THREE.RepeatWrapping; 
textureBump.repeat.set( 2, 2 );

var material = new THREE.MeshPhongMaterial({map: textureDiff, bumpMap: textureBump});

var geometry = new THREE.BoxGeometry( 2, 2, 2 ); 

var cube = new THREE.Mesh( geometry, material ); 
cube.name = "myCube";
cube.position.set( 0, 1, 0 );
cube.castShadow = true;
cube.receiveShadow = true;
scene.add( cube );

我得到了一个带有砖块纹理的立方体。伟大的!我什至可以混合这个顺序,例如,添加带有简单材质的立方体,将其添加到场景中,通过名称找到立方体,然后将其替换为新材质。所有这些都有效。

乍一看,通过 THREE.ObjectLoader 加载对象是可行的。对象就在那里,并且它们的材质颜色指示它们在生成 JSON 的应用程序中分配的材质。如果我询问在此方法中加载的对象,几乎所有我期望并存储在文件中的特征都在那里。但是当我查看对象的材质时,贴图槽为空。所以我查看了 THREE.ObjectLoader 的源代码,从中我收集到可能没有加载材质纹理贴图。 ObjectLoader 遵循MaterialLoader,它似乎没有处理纹理贴图的逻辑。

所以,我也尝试处理解析后的 JSON 场景对象中的材质。在这里,我得到了 JSON 文件中的结构。我浏览了材料、纹理和图像,并从中创建了一系列新的材料。如果我询问新的材质数组,地图包含一个带有图像的纹理对象。我尝试以多种方式加载纹理:

首先,使用 ImageUtils,就像我上面的测试一样:

scene.children[i].material.map =  THREE.ImageUtils.loadTexture('img/brick_diffuse.jpg');

其次,通过实际构建一切,首先加载图像,然后制作纹理,然后制作材质,然后将其应用于对象(这里是材质构建代码)。在这种情况下,如果我删除地图,导入的对象会变成红色:

var loaderImg = new THREE.ImageLoader();
// load a image resource 
loaderImg.load( // resource URL 
    'img/brick_diffuse.jpg', 
    // Function when resource is loaded 
    function ( image ) { // do something with it // like drawing a part of it on a canvas 
console.log("image loaded!");

texture = new THREE.Texture({
    image : image,
    wrapS : THREE.RepeatWrapping,
    wrapT : THREE.RepeatWrapping,
    repeat : [1,1]
});

material = new THREE.MeshPhongMaterial({
    color: new THREE.Color('rgb(0,0,255)'),
    map: texture

    });

//add material to object    
scene.children[i].material = material;                          
},

function ( xhr ) { console.log( (xhr.loaded / xhr.total * 100) + '% loaded' ); }, 
// Function called when download errors 
function ( xhr ) { console.log( 'An error happened' ); } );

我已经尝试了以上的多次迭代,所有结果都指向相同的结果:如果我将贴图添加到我创建的材质中,则对象不会出现,如果我省略材质的贴图属性,则导入的对象改变了材质(可以看到新的颜色和其他属性)。

我在这里看到了几条路: 1. 只需使用解析后的 JSON 场景,忘记 THREE.ObjectLoader,遍历文件中的所有对象,获取它们的关联材料等,一点一点地构建它。 2.扩展THREE.MaterialLoader进去,实际加载图片 3. 有点疯狂。

我在这里看到了几个处理类似问题的问题,但似乎没有明确的答复。我也尝试了一些答案中建议的其他方法,我总是得到一个丢失的对象。

我在 threejs r70 上,在本地和远程服务器上,在 Chrome 和 Firefox 上尝试过。

最后,我尝试了这两件事:

 var textureDiff = THREE.ImageUtils.loadTexture( "img/Cork.png" ); 
    textureDiff.wrapS = THREE.RepeatWrapping; 
    textureDiff.wrapT = THREE.RepeatWrapping; 
    textureDiff.repeat.set( 2, 2 ); 

    var material = new THREE.MeshPhongMaterial({
        color:new THREE.Color('rgb(255,0,0)'),
        map: textureDiff
        });

    var geometry = new THREE.BoxGeometry( 2, 2, 2 );            
    var mmm = new THREE.Mesh(geometry, material );
    scene.add(mmm);

2。在这里,如果我使用导入对象的几何形状来制作新的网格,则网格会消失:

var textureDiff = THREE.ImageUtils.loadTexture( "img/Cork.png" ); 
    textureDiff.wrapS = THREE.RepeatWrapping; 
    textureDiff.wrapT = THREE.RepeatWrapping; 
    textureDiff.repeat.set( 2, 2 );

    var geometry = new THREE.BoxGeometry( 2, 2, 2 ); 

    var material = new THREE.MeshPhongMaterial({
        color:new THREE.Color('rgb(255,0,0)'),
        map: textureDiff
        });

    var mmm = new THREE.Mesh(scene.children[i].geometry, material );
    scene.add(mmm);

如果我注释掉贴图 (//map: textureDiff),导入的几何图形是红色的,呈现材质的颜色。

对于冗长的查询表示歉意,我想确保我记录了我的尝试。我希望我把事情复杂化了,因为我肯定错过了一条简单的信息,说明如果我尝试添加带有纹理的材质,我的对象为什么会消失。 谢谢。

【问题讨论】:

  • 只是为了验证,THREE.ObjectLoader 还不支持这个:github.com/mrdoob/three.js/issues/4967。不过,我应该能够以某种方式将纹理贴图放到几何体上!这是解决此问题的拉取请求:github.com/denzp/three.js/commit/… 构建此版本后,负载管理器确实报告正在加载图像,但我收到其他错误:THREE.WebGLRenderer: WEBGL_compressed_texture_pvrtc extension not supported three.js (line 24404) and TypeError: invalid 'instanceof' 操作数 THREE.ImmediateRenderObject three.js(第 21582 行)

标签: javascript three.js


【解决方案1】:

我正在处理的问题有几个相关的子问题: 1、threejs的r70中的THREE.ObjectLoader不支持材质贴图加载。 2. 我的 JSON 没有包含任何人脸顶点 uvs。

为了解决第一个问题,我查看了源代码和拉取请求,发现了一个modification to the object loader。由于这些更改没有编译到库中,我构建了一个混合的threejs,将当前版本的ObjectLoader 替换为此拉取请求中的版本。

为了解决第二个问题,我将应用程序中的网格面顶点 uvs 添加到正在写入的 json 文件中。

拉取请求现在是merged with the dev branch of threejs

感谢@denzp 的修改和感谢@mrdoob(和其他贡献者)在threejs 上的出色工作。

【讨论】:

    猜你喜欢
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 2018-09-07
    • 2014-09-26
    • 2019-08-12
    • 1970-01-01
    相关资源
    最近更新 更多