threejs - 将带有纹理贴图的材质应用于通过 THREE.ObjectLoader 加载的对象
threejs - apply materials with texture maps to objects loaded through THREE.ObjectLoader
我正在通过 JSON 文件引入几何和 materials。在大多数情况下,这很有效,除了现在我还尝试引入纹理贴图。据我所知,THREE.ObjectLoader 从加载的纹理中删除了任何图像信息,因此,material 无法访问图像源。 我尝试了几种方法,但它们都导致了相同的结果:如果我使用纹理贴图重新创建 material 并将其应用于加载的对象,该对象就会消失。
为了确保某些东西能够正常工作,我用一个立方体和一个 material 创建了一个简单的场景。这很好用:
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 );
我得到了一个带有砖块纹理的立方体。伟大的!我什至可以混合顺序,例如,添加带有简单 material 的立方体,将其添加到场景中,根据其名称找到立方体,然后将其替换为新的 material。所有这些都有效。
通过 THREE.ObjectLoader 加载对象乍一看是可行的。对象在那里,并且它们具有 material 颜色,表示它们在生成 JSON 的应用程序中分配的 material。如果我询问一个用这种方法加载的对象,几乎所有我期望的和存储在文件中的特征都在那里。但是当我查看对象的 material 时,地图插槽为空。所以我查看了 THREE.ObjectLoader 的来源,从中我收集到可能 material 纹理贴图未加载。 ObjectLoader 遵从 MaterialLoader,它似乎没有处理纹理贴图的逻辑。
所以,我也尝试从解析的 JSON 场景对象中处理 materials。在这里,我得到了我在 JSON 文件中的结构。我遍历 materials、纹理和图像,并从中创建一个新的 materials 数组。如果我询问新的 material 数组,地图包含一个带有图像的纹理对象。我试过以几种方式加载纹理:
首先,像我上面的测试一样使用 ImageUtils:
scene.children[i].material.map = THREE.ImageUtils.loadTexture('img/brick_diffuse.jpg');
其次,通过实际构造一切,首先加载图像,然后制作纹理,然后制作 material,然后将其应用于对象(这里是 material 构造代码).在这种情况下,如果我删除地图,导入的对象会变成红色:
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' ); } );
我已经尝试了上面的多次迭代,所有结果都指向相同的结果:如果我将地图添加到 material 我创建的对象不会出现,如果我省略地图material 的属性,导入的对象更改 material(可以看到新的颜色和其他属性)。
我在这里看到几条路:
1. 只需使用已解析的 JSON 场景而忘记 THREE.ObjectLoader,遍历文件中的所有对象,获取它们关联的 material 等,一点一点地构建它。
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),导入的几何图形为红色,呈现 material.
的颜色
对于冗长的查询表示歉意,我想确保我记录了我的尝试。我希望我把事情复杂化了,因为我肯定遗漏了一条简单的信息,说明如果我尝试添加带有纹理的 material,为什么我的对象会消失。
谢谢。
我正在处理的问题有几个相关的子问题:
1、threejs的r70中的THREE.ObjectLoader不支持material纹理加载。
2. 我的 JSON 没有包含任何面顶点 uvs。
为了解决第一个问题,我查看了源代码并通过拉取请求找到了 modification to the object loader。由于这些更改未编译到库中,我构建了一个混合的 threejs,将当前修订版 ObjectLoader 替换为此拉取请求中的那个。
为了解决第二个问题,我将应用程序中的网格面顶点 uvs 添加到正在写入的 json 文件中。
拉取请求现已 merged with the dev branch of threejs。
感谢@denzp 的修改和@mrdoob(以及其他贡献者)在 threejs 上的出色工作。
我正在通过 JSON 文件引入几何和 materials。在大多数情况下,这很有效,除了现在我还尝试引入纹理贴图。据我所知,THREE.ObjectLoader 从加载的纹理中删除了任何图像信息,因此,material 无法访问图像源。 我尝试了几种方法,但它们都导致了相同的结果:如果我使用纹理贴图重新创建 material 并将其应用于加载的对象,该对象就会消失。
为了确保某些东西能够正常工作,我用一个立方体和一个 material 创建了一个简单的场景。这很好用:
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 );
我得到了一个带有砖块纹理的立方体。伟大的!我什至可以混合顺序,例如,添加带有简单 material 的立方体,将其添加到场景中,根据其名称找到立方体,然后将其替换为新的 material。所有这些都有效。
通过 THREE.ObjectLoader 加载对象乍一看是可行的。对象在那里,并且它们具有 material 颜色,表示它们在生成 JSON 的应用程序中分配的 material。如果我询问一个用这种方法加载的对象,几乎所有我期望的和存储在文件中的特征都在那里。但是当我查看对象的 material 时,地图插槽为空。所以我查看了 THREE.ObjectLoader 的来源,从中我收集到可能 material 纹理贴图未加载。 ObjectLoader 遵从 MaterialLoader,它似乎没有处理纹理贴图的逻辑。
所以,我也尝试从解析的 JSON 场景对象中处理 materials。在这里,我得到了我在 JSON 文件中的结构。我遍历 materials、纹理和图像,并从中创建一个新的 materials 数组。如果我询问新的 material 数组,地图包含一个带有图像的纹理对象。我试过以几种方式加载纹理:
首先,像我上面的测试一样使用 ImageUtils:
scene.children[i].material.map = THREE.ImageUtils.loadTexture('img/brick_diffuse.jpg');
其次,通过实际构造一切,首先加载图像,然后制作纹理,然后制作 material,然后将其应用于对象(这里是 material 构造代码).在这种情况下,如果我删除地图,导入的对象会变成红色:
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' ); } );
我已经尝试了上面的多次迭代,所有结果都指向相同的结果:如果我将地图添加到 material 我创建的对象不会出现,如果我省略地图material 的属性,导入的对象更改 material(可以看到新的颜色和其他属性)。
我在这里看到几条路: 1. 只需使用已解析的 JSON 场景而忘记 THREE.ObjectLoader,遍历文件中的所有对象,获取它们关联的 material 等,一点一点地构建它。 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),导入的几何图形为红色,呈现 material.
的颜色对于冗长的查询表示歉意,我想确保我记录了我的尝试。我希望我把事情复杂化了,因为我肯定遗漏了一条简单的信息,说明如果我尝试添加带有纹理的 material,为什么我的对象会消失。 谢谢。
我正在处理的问题有几个相关的子问题: 1、threejs的r70中的THREE.ObjectLoader不支持material纹理加载。 2. 我的 JSON 没有包含任何面顶点 uvs。
为了解决第一个问题,我查看了源代码并通过拉取请求找到了 modification to the object loader。由于这些更改未编译到库中,我构建了一个混合的 threejs,将当前修订版 ObjectLoader 替换为此拉取请求中的那个。
为了解决第二个问题,我将应用程序中的网格面顶点 uvs 添加到正在写入的 json 文件中。
拉取请求现已 merged with the dev branch of threejs。
感谢@denzp 的修改和@mrdoob(以及其他贡献者)在 threejs 上的出色工作。