4
votes

I have come to a brick wall in the development of my project. I am attempting to achieve a level using various types of phong materials on unique sized and shaped objects. By default, Three.JS handles textures in a way that they stretch out and become unbearable to look at when presented on a mesh that's not exactly 1:1:1 ratio size, meaning everything has to be cubes or perfect sized spheres to look normal. To circumvent this problem, you can load textures with repeat options. The problem with this approach is that with 100+ unique sized objects, those repeat options have to be different for each material, for each object. This means loading in hundreds of textures or filling up the memory with clones. The latter not bothering me too much. I need help trying to figure out how to deal with mass amounts of unique objects with unique geometries and unique colormaps, emissivemaps, specularmaps, aomaps, bumpmaps, and normalmaps. How can I make it feasable to have 1 texture with unique repeat settings based on material? Even if I have this solved, I have to repeat 5+ textures per material. 5*~100 = ~500 textures/texture variations. This is a problem. 100 at least, 800 at most.

I am very desperate about this, and I am considering switching to Unity or UE4 if I can't deal with objects in bulk.

I am open to completely reworking my code from square 1. This is nothing special, and it's very crude. But I want to show the way I handle objects in THREE.js. This is not my complete program (obviously), it is merely an example of how I do things.

var energyRockMaterial =
  new THREE.MeshPhongMaterial(
    {
        envMap: scene.background,
        map: new THREE.TextureLoader().load("energyrock.jpg"),
        normalMap: new THREE.TextureLoader().load("energyrocknormal.jpg"),
        //bumpMap: new THREE.TextureLoader().load("energyrockbump.jpg"),
        aoMap: new THREE.TextureLoader().load("energyrockao.jpg"),
        specularMap: new 
        THREE.TextureLoader().load("energyrockspecular.jpg"),
        emissiveMap: new 
        THREE.TextureLoader().load("energyrockemissive.jpg"),
        color:"#ffffff",
        emissive:"#bb00bb",
        specular:"#000000",
        reflectivity:1,
    });
var energyRockGeometry = new THREE.BoxBufferGeometry(1,1,1);
var energyRockMesh = new 
THREE.Mesh(energyRockGeometry,energyRockMaterial);
scene.add(energyRockMesh)

Apologies for problematic indenting, HTML form wasn't enjoying my tabs, and I had to gimp this out.

Thanks for the responses.

1
Try this pattern: mesh.onBeforeRender = function() { this.material.map.repeat.x = this.userData.repeatx; }; That way, the cloned materials can all share the same texture.WestLangley
Is your entire scene composed of cubes and primitive shapes? Or are you loading models from external files?Don McCurdy
I am using primitive shapes, and I don't plan to change it.user10322453

1 Answers

0
votes

First, read up on UV mapping. In a nutshell, UVs are texture coordinates that you assign to vertices. They tell the renderer what point on a texture maps to what vertex on a mesh, and the renderer handles the rest, mapping the texture across the triangle.

THREE.js supports UVs through both Geometry and BufferGeometry. (In my opinion, the latter is easier to use for this.)

The nice thing about this as it applies to your situation is that you can use a single material for multiple shapes. Shapes with unique UVs will map the texture uniquely. In other words, a cube with one set of UVs could have the same material as another cube with different UVs, and they would each map the texture according to their own UVs.

Secondly, and probably less relevant to your situation, you could look into using a texture atlas. This is one large image file containing multiple textures. Even if all you shapes have different textures, you could (potentially) load a single image file, put it in a single material for the meshes to share, and they would use their unique UVs to map to the texture sections relevant to them.