javascriptthree.jswebglbump-mapping

Displacement map in three.js


I'm currently using a black and white image as a bump map for my model. The model is an .obj file with the associated .mtl file for UV mapping. This is the code I use:

            // Load material file
            var mtlLoader = new THREE.MTLLoader();
            mtlLoader.setPath('/models/');
            mtlLoader.load('model.mtl', function (materials) {
                materials.preload();

                // Load obj file
                var objLoader = new THREE.OBJLoader();
                objLoader.setMaterials(materials);
                objLoader.setPath('/models/');
                objLoader.load('model.obj', function (group) {

                    var geometry = group.children[0].geometry;  
                    model = new THREE.Mesh(geometry, otherModel.material.clone());
                    scene.add(model);

                    render();
                    callback();
                });
            });

At a latter time I add the bump map when I need it:

            model.material.bumpMap = new THREE.Texture(canvas);
            model.material.bumpScale = 0.8;
            model.material.bumpMap.format = THREE.RGBFormat;
            model.material.bumpMap.wrapS = mapRingModel.material.bumpMap.wrapT = THREE.RepeatWrapping;
            model.material.bumpMap.minFilter = THREE.LinearFilter;

            model.material.bumpMap.needsUpdate = true;
            model.material.needsUpdate = true;

This works as expected but now I would like to use my texture as a displacement map instead of a bump map so I changed my code to:

            model.material.displacementMap = new THREE.Texture(canvas);
            model.material.displacementScale = 0.8;
            model.material.displacementMap.format = THREE.RGBFormat;
            model.material.displacementMap.wrapS = model.material.displacementMap.wrapT = THREE.RepeatWrapping;
            model.material.displacementMap.minFilter = THREE.LinearFilter;

            model.material.displacementMap.needsUpdate = true;
            model.material.needsUpdate = true;

With the same texture applied the displacement is no applied at all. Is there anything I need to change on my UV mapping or texture to work as the bump map but with displacement?


Solution

  • I don't see anything wrong with your code. Are you sure it's not working?
    Try upping the value of displacementScale.
    While bumpScale is from 0 - 1. DisplacementScale can be anything as it is .. umm...scene scale.
    below is an example of both working together with canvas as texture (draw in boxes to see), click "run code snippet"

    var camera, scene, renderer, mesh, material, stats;
    var drawStartPos = {x:0, y:0};
    
    init();
    setupCanvasDrawing();
    animate();
    
    function init() {
        // Renderer.
        renderer = new THREE.WebGLRenderer();
        //renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        // Add renderer to page
        document.getElementById('threejs-container').appendChild(renderer.domElement);
    
        // Create camera.
        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
        camera.position.z = 400;
    
        // Create scene.
        scene = new THREE.Scene();
    
        // Create material
        material = new THREE.MeshPhongMaterial();
    
        // Create cube and add to scene.
        var geometry = new THREE.BoxGeometry(200, 200, 200, 50, 50, 50);
        mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);
    
        // Create ambient light and add to scene.
        var light = new THREE.AmbientLight(0x404040); // soft white light
        scene.add(light);
    
        // Create directional light and add to scene.
        var directionalLight = new THREE.DirectionalLight(0xffffff);
        directionalLight.position.set(1, 1, 1).normalize();
        scene.add(directionalLight);
    
        // Add listener for window resize.
        window.addEventListener('resize', onWindowResize, false);
    
        // Add stats to page.
        stats = new Stats();
        document.body.appendChild( stats.dom );
    }
    
    function setupCanvasDrawing() {
    		// get canvas and context
    		var drawingCanvas = document.getElementById('drawing-canvas');
        var drawingCanvas2 = document.getElementById('drawing-canvas-2');
        var drawingContext = drawingCanvas.getContext('2d');
        var drawingContext2 = drawingCanvas2.getContext('2d');
        
        // draw white background
        drawingContext.fillStyle = "#FFFFFF";
        drawingContext.fillRect(0,0,128,128);
        drawingContext2.fillStyle = "#000000";
        drawingContext2.fillRect(0,0,128,128);
        
        // set canvas as bumpmap
        material.bumpMap = new THREE.Texture(drawingCanvas);
        material.displacementMap = new THREE.Texture(drawingCanvas2);
        material.displacementScale = 30;
        
        // set the variable to keep track of when to draw
        var paint = false;
        var paint2 = false;
        
        // add canvas event listeners
        drawingCanvas.addEventListener('mousedown', function(e){
          paint = true
          drawStartPos = {x:e.offsetX, y:e.offsetY};
        });
        drawingCanvas.addEventListener('mousemove', function(e){
        	if(paint){
          	draw(drawingContext, 0, e.offsetX, e.offsetY);
          }
        });
        drawingCanvas.addEventListener('mouseup', function(e){
          paint = false;
        });
        drawingCanvas.addEventListener('mouseleave', function(e){
          paint = false;
        });
        
        drawingCanvas2.addEventListener('mousedown', function(e){
          paint2 = true
          drawStartPos = {x:e.offsetX, y:e.offsetY};
        });
        drawingCanvas2.addEventListener('mousemove', function(e){
        	if(paint2){
          	draw(drawingContext2, 1, e.offsetX, e.offsetY);
          }
        });
        drawingCanvas2.addEventListener('mouseup', function(e){
          paint2 = false;
        });
        drawingCanvas2.addEventListener('mouseleave', function(e){
          paint2 = false;
        });
    }
    
    // Draw function
    function draw(drawContext, type,  x, y) {
      drawContext.moveTo(drawStartPos.x, drawStartPos.y);
      if(type){
      	// is displacement
        drawContext.strokeStyle = '#ffffff';
      }else{
      	// is bump
        drawContext.strokeStyle = '#000000';
      }
    	drawContext.lineTo(x,y);
    	drawContext.stroke();
      drawStartPos = {x:x, y:y};
      material.bumpMap.needsUpdate = true;
      material.displacementMap.needsUpdate = true;
    }
    
    function animate() {
        requestAnimationFrame(animate);
        mesh.rotation.x += 0.005;
        mesh.rotation.y += 0.01;
        renderer.render(scene, camera);
        stats.update();
    }
    
    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }
    body {
        padding: 0;
        margin: 0;
    }
    
    #drawing-canvas {
      position: absolute;
      background-color: #000;
      top: 0px;
      right: 0px;
      z-index: 3;
    }
    #drawing-canvas-2 {
      position: absolute;
      background-color: #000;
      top: 128px;
      right: 0px;
      z-index: 3;
      border: solid 1px #ffffff;
    }
    
    #threejs-container {
      position: absolute;
      left: 0px;
      top: 0px;
      width: 100%;
      height: 100%;
      z-index: 1;
    }
    <script src="https://rawgit.com/mrdoob/three.js/r83/build/three.min.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/stats.js/r17/build/stats.min.js"></script>
    <canvas id="drawing-canvas" height="128" width="128"></canvas>
    <canvas id="drawing-canvas-2" height="128" width="128"></canvas>
    <div id="threejs-container"></div>