使用外部链接将纹理应用于WebGL中的3D模型

时间:2018-05-22 19:40:38

标签: javascript 3d three.js webgl textures

我刚学会了如何使用.mtl文件(和.obj文件)在WebGL中将纹理应用于我的3D模型。当图像保存在我的计算机上时,应用纹理效果很好。以下是我的.mtl文件的示例:

newmtl Earth_MATERIAL
Ns 96.078431
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 1

map_Kd Earth.png

这非常有效。但是我想发布我的模拟,因此我必须以某种方式参考图像。我的第一个想法是将图像上传到DropBox并使用该链接,但这不起作用:

...
map_Kd https://dl.dropbox.com/s/t4cm3vzsbx21crc/Earth.png?dl=0

运行此代码时出现的错误是:

  

错误:WebGL警告:texImage2D:元素是只写的,因此无法上传。

要加载纹理和模型,我使用MTLloader和OBJloader。以下是我正在使用的装载机:

MTLloader:link

OBJloader:link

我也使用ThreeJS Library:

ThreeJS:link

编辑: 由于Jave,问题解决了!以下是希望查看的人的结果:https://code.sololearn.com/WWY9cXN6OVBX/

1 个答案:

答案 0 :(得分:0)

MTLLoader有一个名为setTexturePath的方法,您可以使用该方法设置加载纹理的基本路径。由于您使用文件的外部源(dropbox),因此您可能还需要调用setCrossOrigin(true)。我附上了一个使用这些方法加载纹理的注释示例。

您可能需要考虑的一些事项:

  • 通常你会把你的纹理放在与。相同的目录中 mtl-file或子目录,以便您可以直接引用它们(如 只需Earth.pngtextures/Earth.png)。
  • 如果您使用的是mipmaps,则必须使用纹理尺寸 例如,2的幂(2048 x 1024)。你的形象不是 加载时自动调整大小。它会更有效率 事先手动调整大小。
  • 您的纹理是5689 x 2844像素。这对纹理来说非常大 你应该减少它。有些移动设备可能不会 能够使用大于2048 x 2048的纹理。

const canvas = document.getElementById("canvas");
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, 1, 1, 10);
const renderer = new THREE.WebGLRenderer({ canvas });
const light = new THREE.AmbientLight();
scene.add(light);
camera.position.set(0, 0, 6);

const mesh = new THREE.Mesh(new THREE.SphereBufferGeometry( 1, 32, 32 ));
scene.add(mesh);


function update(){
  scene.rotation.y = 0.001 * performance.now();
  renderer.render(scene, camera);

  requestAnimationFrame(update);
}

update();

//This is just creating a data-url from the div containing the mtl-data, it is not really neccessary, but it will make the example more similiar to loading a file.
const data = document.getElementById("mtlplaceholder").textContent;
const dataurl = "data:text/plain;base64," + btoa(data);

const loader = new THREE.MTLLoader();

//To load texture files not in the same folder as the mtl-file, we need to call setTexurePath with the proper base path. Note that every texture will have to be available at this same base url, which might not be the case when shared from dropbox.
//The complete URL is  https://dl.dropbox.com/s/t4cm3vzsbx21crc/Earth.png
loader.setTexturePath("https://dl.dropbox.com/s/t4cm3vzsbx21crc/");
//To use cross-origin loading of textures, call setCrossOrigin(true):
loader.setCrossOrigin(true);
//Finally. load the mtl file (in this case the "file" is the dataurl created above):
loader.load(dataurl, res => {
  //MTLLoader.load creates a MTLLoader.MaterialCreator, to get the actual material we have to call create with the name of the material we want.
  //If you are using the OBJLoader, use preload instead and then objloader.setMaterials.
  const loadedMat = res.create("Earth_MATERIAL");
  //Finally, we set the material on the mesh.
  mesh.material = loadedMat;
}, e => console.log("error", e));
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/53838a2/examples/js/loaders/MTLLoader.js"></script>

<canvas id="canvas" width="400" height="400"></canvas>

<div id="mtlplaceholder" style:"white-space:pre">
newmtl Earth_MATERIAL
Ns 96.078431
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 1

map_Kd Earth.png
</div>