3

I'm trying to apply a bump map to a plane to create a vaguely felt-like surface using Three.js r55.

Here's my code:

var mapHeight = THREE.ImageUtils.loadTexture("images/felt.png");
mapHeight.repeat.set(2, 2);
mapHeight.wrapS = mapHeight.wrapT = THREE.RepeatWrapping;
mapHeight.format = THREE.RGBFormat;

var groundMaterial = new THREE.MeshPhongMaterial({
    ambient: 0x008800, color: 0x008800, specular: 0x888888,
    shininess: 25, bumpMap: mapHeight, bumpScale: 10, metal: false
} );

scene.add(new THREE.Mesh(new THREE.PlaneGeometry(0.3, 0.3), groundMaterial));

Notice how I set the texture to repeat twice along x/y axes. However what I'm seeing only applies the texture in one quadrant:

I would expect this with clamp/repeat wrapping (or whatever it's called) but I've requested RepeatWrapping here.

How can I have the bump map correctly repeat an arbitrary number of times on the plane.


EDIT - Full Code

I set about making a simple reproduction case. This is pretty minimal and reproduces the image below (from a slightly different camera angle.) The output has the identical problem.

<!DOCTYPE html>
<html>
<head>
    <script src="scripts/libs/three.min.js" type="text/javascript"></script>
</head>
<body>
<div id="scene-container"></div>

<script>

    init();

    function init() {
        var camera, scene, renderer;

        scene = new THREE.Scene();
        scene.add( new THREE.AmbientLight( 0x555555 ) );

        var light = new THREE.DirectionalLight( 0x555555 );
        light.position.set( 0, 0, 10 );
        scene.add( light );

        var bumpMapTexture = THREE.ImageUtils.loadTexture( "images/felt.png", undefined, function () {
            requestAnimationFrame( function () {
                // render once texture has loaded
                renderer.render( scene, camera );
            } );
        } );
        bumpMapTexture.repeat.set( 2, 2 );
        bumpMapTexture.wrapS = bumpMapTexture.wrapT = THREE.RepeatWrapping;

        var groundMaterial = new THREE.MeshPhongMaterial( {
            ambient: 0x00AA00,
            color: 0x00AA00,
            bumpMap: bumpMapTexture
        } );

        scene.add( new THREE.Mesh( new THREE.PlaneGeometry( 3, 3 ), groundMaterial ) );

        camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.01, 100000 );
        camera.position.set( 0, 0, 3 );
        camera.lookAt( new THREE.Vector3( 0, 0, 0 ) );

        renderer = new THREE.WebGLRenderer( { antialias: true } );
        renderer.setSize( window.innerWidth, window.innerHeight );//        renderer.render(scene, camera);

        document.getElementById( 'scene-container' ).appendChild( renderer.domElement );
    }

</script>

</body>
</html>

This links to Three.js r55 (minified).

Any help appreciated.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742

1 Answers1

6

If you want a texture to repeat, it's size in pixels in each dimension must be a power of two ( e.g., 512 x 256 ).

If you have a diffuse map and a bumpMap, they must have the same offset/repeat settings. See for example this answer.

three.js r.55

Community
  • 1
  • 1
WestLangley
  • 102,557
  • 10
  • 276
  • 276
  • I'll try this out in the next 24 hours and get back to you. Thanks very much for your help. – Drew Noakes Feb 15 '13 at 10:55
  • I'm looking at this again now. Setting both the bump and diffuse maps to the same instance still gives me the same issue as pictured. I will try quickly to reproduce this issue before attempting an alternative way of texturing the material. – Drew Noakes Feb 24 '13 at 00:37
  • I've updated my question with code that should help you reproduce the problem. I've tested in both Firefox and Chrome on Ubuntu 12.04. – Drew Noakes Feb 24 '13 at 01:40
  • Your updated code works fine for me. However, I was able to reproduce your problem when I used a non-power-of-two texture. Is that it? – WestLangley Feb 24 '13 at 02:07
  • Fantastic! Yes it seems obvious now that you point it out, but my texture was rectangular and neither dimension was a power of two. Thanks very much for this. Do you think it would be useful if Three.js logged out a console warning if a loaded texture had non-power-of-two dimensions? – Drew Noakes Feb 24 '13 at 15:59
  • Perhaps, in this case. Three.js supports NPOT textures, however, and attempts to handle them gracefully. – WestLangley Feb 24 '13 at 16:31