Material displacement map makes the texture unwrap the model's surfaces

I have a cube fbx model with MeshPhongMaterial and textures with 3 maps: color, displacement and normal 16bit. At first I used the displacement map loaded from .tif file, the texture wrapped but no bump on the model’s surfaces, and in the console the displacementMap was null. Later I converted that tif file to .jpg file, the displacementMap is now filled, but the texture is kind of floating on the model surface. I applied the same thing with an sphere model, the texture wrapped and bumped perfectly. Could you check it out and see what’s wrong? Thanks a lot!

All of my maps having the size of 2048x2048, in case you think it’s the model’s size problem.

Here is the loading texture code:

var textureLoader = new THREE.TextureLoader();

if (THREE.Cache.enabled) {
    var textureColor = THREE.Cache.get(textureName + 'Color');
    var textureDisplace = THREE.Cache.get(textureName + 'Displace'); // get from cache
    var textureNormal = THREE.Cache.get(textureName + 'Normal');

    if (textureColor) {
        object.material.map = textureColor;
    } else {
        textureLoader.load('../assets/models/textures/' + textureName + '/color.jpg', (texture) => {
            THREE.Cache.add(textureName + 'Color', texture);
            object.material.map = texture;
        });
    }

    // load from file
    if (textureDisplace) {
        object.material.displacementMap = textureDisplace;
        object.material.displacementScale = 1.05;
        object.material.displacementBias = 0.01;
    } else {
        textureLoader.load('../assets/models/textures/' + textureName + '/displace.jpg', (texture) => {
            THREE.Cache.add(textureName + 'Displace', texture);
            object.material.displacementMap = texture;
            object.material.displacementScale = 2.5;
            object.material.displacementBias = 0.01;
        });
    }

    if (textureNormal) {
        object.material.normalMap = textureNormal;
    } else {
        textureLoader.load('../assets/models/textures/' + textureName + '/normal.jpg', (texture) => {
            THREE.Cache.add(textureName + 'Normal', texture);
            object.material.normalMap = texture;
        });
    }
}

object.userData.texture = textureName;

Here is how the cube model looks like:
1-203-2018-11-26-17-30-14-579

Here is the sphere:
1-203-2018-11-26-17-27-05-467

Here is the LIVE DEMO.

Can you please share the cube rendering as a live demo? Not the entire app, please. Just an isolated test that demonstrates the render issue.

1 Like

@Mugen87 I’ve added the live demo above

1 Like

Um, it seems to me that the displacement map transforms the vertices along their face normal. Since the vertices of a single side are not connected with the vertices of its adjacent sides, the visual result looks a bit strange. This effect becomes very visible if you turn down the strength of the effect by setting a low value for displacementScale.

1 Like

@Mugen87 wow thanks! It’s OK now :+1:

@Mugen87 is there any way to set the scale and bias of displacement map without having the planes floating away? I’ve tried all kind of bias and scale value above 0 and the issue just kept happening. Set to 0 and it’s just like there’s no displacement at all, but it keeps the sides touch.

I don’t think this is possible because the sides of the box are not connected with each other. Maybe you have more luck with a custom geometry.

1 Like

For future readers wondering why their displacement map does nothing but float the texture away from your 3D object, it’s because the geometry underneath the texture doesn’t have enough vertices to create a displacement.

Using the same example as above I added additional vertices to the BoxGeometry then offset that with a displacementBias. Bing bang boom you’ve got displacement. https://jsfiddle.net/uam5h8r6/.

Making the cube a little bigger and setting the material wireframe to true shows that it’s the geometry vertices that are being displaced via the displacementMap and the texture then being applied to those vertices. https://jsfiddle.net/uam5h8r6/1/

2 Likes

Hello @DeptofJeffAyer,

Is there a way to add vertices to existing BufferGeometry in order to force displacement?

@Samuel I’ve been struggling with that very problem myself on a project and it has turned out to be a real can of worms. Since your post I started researching how THREE was converting its geometry functions into BufferGeometries starting with the PlaneGeometry. I was mainly focusing on how THREE converts the segments into vertices. That led me into some of the core functions which ultimately led me back to what I was doing in the first place because of time constraints.

Have you made any progress on your end since your post?

@DeptofJeffAyer I’ve made some progress but not enough to get a perfect geometry displacement. Here’s my incomplete solution:

  • Load a modified version of THREE SubdivisionModifier.
    That modified version retains shape. See SO question.
    return geometry; must be added to modify function.
  • Subdivide each mesh 8 times (more crashes browser).
  • Apply a displacement texture on each mesh, of course.