How to add map and roughnessMap in ThreeJS?

Viewed 487

This is the code I am working with:

* {
  margin: 0;
  padding: 0;
}

.object {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  pointer-events: none;
  background-color: rgb(200, 200, 200);
}
<script type="module">
import * as THREE from "https://threejs.org/build/three.module.js";
import { OBJLoader } from "https://threejs.org/examples/jsm/loaders/OBJLoader.js";
import { EXRLoader } from "https://threejs.org/examples/jsm/loaders/EXRLoader.js";

var container;
var camera, scene, renderer;
let exrCubeRenderTarget, exrBackground;
let newEnvMap;
let torusMesh, planeMesh;

var mouseX = 0,
    mouseY = 0;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

var object;

init();
animate();

function init() {
    container = document.createElement("div");
    container.className = "object";
    document.body.appendChild(container);

    camera = new THREE.PerspectiveCamera(
        45,
        window.innerWidth / window.innerHeight,
        1,
        2000
    );
    camera.position.z = 250;

    // scene

    scene = new THREE.Scene();

    /*var ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
    scene.add(ambientLight);
    var pointLight = new THREE.PointLight(0xffffff, 2);
    pointLight.position.set(100, 100, 50);
    camera.add(pointLight);*/

    scene.add(camera);

    // manager
    function loadModel() {
        THREE.DefaultLoadingManager.onLoad = function () {
            pmremGenerator.dispose();
        };

        // -----------------

        function loadObjectAndAndEnvMap() {
            object.traverse(function (child) {
                //This allow us to check if the children is an instance of the Mesh constructor
                if (child instanceof THREE.Mesh) {
                    child.material = new THREE.MeshStandardMaterial({
                        color: "#555",
                        roughness: 0.0,
                        metalness: 2.0,
                        envMapIntensity: 5.0
                    });
                    //child.material.flatShading = false;

                    console.log("setting envmap");
                    child.material.envMap = newEnvMap;
                    child.material.needsUpdate = true;

                    //Sometimes there are some vertex normals missing in the .obj files, ThreeJs will compute them
                }
            });
            object.position.y = -90;
            scene.add(object);
        }

        const pmremGenerator = new THREE.PMREMGenerator(renderer);
        pmremGenerator.compileEquirectangularShader();

        new EXRLoader()
            .setDataType(THREE.UnsignedByteType)
            .load(
                "https://threejs.org/examples/textures/piz_compressed.exr",
                function (texture) {
                    exrCubeRenderTarget = pmremGenerator.fromEquirectangular(texture);
                    exrBackground = exrCubeRenderTarget.texture;
                    newEnvMap = exrCubeRenderTarget ? exrCubeRenderTarget.texture : null;

                    loadObjectAndAndEnvMap(); // Add envmap once the texture has been loaded

                    texture.dispose();
                }
            );

        renderer.toneMapping = THREE.ACESFilmicToneMapping;
        renderer.outputEncoding = THREE.sRGBEncoding;
    }

    var manager = new THREE.LoadingManager(loadModel);

    manager.onProgress = function (item, loaded, total) {
        console.log(item, loaded, total);
    };

    // model
    function onProgress(xhr) {
        if (xhr.lengthComputable) {
            var percentComplete = (xhr.loaded / xhr.total) * 100;
            console.log("model " + Math.round(percentComplete, 2) + "% downloaded");
        }
    }
    function onError() {}
    var loader = new OBJLoader(manager);
    loader.load(
        "https://threejs.org/examples/models/obj/female02/female02.obj",
        function (obj) {
            object = obj;
        },
        onProgress,
        onError
    );

    //

    renderer = new THREE.WebGLRenderer({ alpha: true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    container.appendChild(renderer.domElement);

    document.addEventListener("mousemove", onDocumentMouseMove, false);

    //

    window.addEventListener("resize", onWindowResize, false);
}

function onWindowResize() {
    windowHalfX = window.innerWidth / 2;
    windowHalfY = window.innerHeight / 2;

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);
}

function onDocumentMouseMove(event) {
    mouseX = (event.clientX - windowHalfX) / 2;
    mouseY = (event.clientY - windowHalfY) / 2;
}

//

function animate() {
    requestAnimationFrame(animate);
    render();
}

function render() {
    camera.position.x += (mouseX - camera.position.x) * 0.05;
    camera.position.y += (-mouseY - camera.position.y) * 0.05;

    camera.lookAt(scene.position);

    scene.background = exrBackground;
    renderer.toneMappingExposure = 1.0;
    renderer.render(scene, camera);
}
</script>

Now I want to add map and roughnessMap like here: https://threejs.org/docs/scenes/material-browser.html#MeshStandardMaterial

I thought I just should add the following:

const textureLoader = new THREE.TextureLoader();


const diffuseMaps = (function() {

  const bricks = textureLoader.load('https://threejs.org/examples/textures/brick_diffuse.jpg');
  bricks.wrapS = RepeatWrapping;
  bricks.wrapT = RepeatWrapping;
  bricks.repeat.set(9, 1);

  return {
    none: null,
    bricks: bricks
  };

})();


const roughnessMaps = (function() {

  const bricks = textureLoader.load('https://threejs.org/examples/textures/brick_roughness.jpg');
  bricks.wrapT = RepeatWrapping;
  bricks.wrapS = RepeatWrapping;
  bricks.repeat.set(9, 1);

  return {
    none: null,
    bricks: bricks
  };

})();


function loadObjectAndAndEnvMap() {
  object.traverse(function(child) {
    //This allow us to check if the children is an instance of the Mesh constructor
    if (child instanceof THREE.Mesh) {
      child.material = new THREE.MeshStandardMaterial({
        color: "#555",
        roughness: 0.0,
        metalness: 2.0,
        envMapIntensity: 5.0,
        diffuseMapIntensity: 1.0,
        roughnessMapIntensity: 1.0
      });
      //child.material.flatShading = false;

      console.log("setting envmap");
      child.material.envMap = newEnvMap;
      child.material.diffuseMap = diffuseMaps;
      child.material.roughnessMap = roughnessMaps;
      child.material.needsUpdate = true;

      //Sometimes there are some vertex normals missing in the .obj files, ThreeJs will compute them
    }
  });
  object.position.y = -90;
  scene.add(object);
}

Unfortunately, it does not work.

Could somebody help me please? I would be sooo thankful!!

1 Answers

Try it with this code:

var container;
var camera, scene, renderer;
let exrCubeRenderTarget, exrBackground;
let newEnvMap;
let torusMesh, planeMesh;

var mouseX = 0,
  mouseY = 0;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

var object;

init();
animate();

function init() {
  container = document.createElement("div");
  container.className = "object";
  document.body.appendChild(container);

  camera = new THREE.PerspectiveCamera(
    45,
    window.innerWidth / window.innerHeight,
    1,
    2000
  );
  camera.position.z = 250;

  // scene

  scene = new THREE.Scene();
  scene.add(camera);

  // manager
  function loadModel() {
    THREE.DefaultLoadingManager.onLoad = function() {
      pmremGenerator.dispose();
    };

    // -----------------

    function loadObjectAndAndEnvMap() {
    
      const textureLoader = new THREE.TextureLoader();
      const diffuseMap = textureLoader.load('https://threejs.org/examples/textures/brick_diffuse.jpg');
      const roughnessMap = textureLoader.load('https://threejs.org/examples/textures/brick_roughness.jpg');
    
      object.traverse(function(child) {
        //This allow us to check if the children is an instance of the Mesh constructor
        if (child instanceof THREE.Mesh) {
          child.material = new THREE.MeshStandardMaterial({
            color: "#555",
            roughness: 1.0,
            metalness: 0.5,
            envMapIntensity: 5.0
          });

          child.material.envMap = newEnvMap;
          child.material.map = diffuseMap;
          child.material.roughnessMap = roughnessMap;
          child.material.needsUpdate = true;

          //Sometimes there are some vertex normals missing in the .obj files, ThreeJs will compute them
        }
      });
      object.position.y = -90;
      scene.add(object);
    }

    const pmremGenerator = new THREE.PMREMGenerator(renderer);
    pmremGenerator.compileEquirectangularShader();

    new THREE.EXRLoader()
      .setDataType(THREE.UnsignedByteType)
      .load(
        "https://threejs.org/examples/textures/piz_compressed.exr",
        function(texture) {
          exrCubeRenderTarget = pmremGenerator.fromEquirectangular(texture);
          exrBackground = exrCubeRenderTarget.texture;
          newEnvMap = exrCubeRenderTarget ? exrCubeRenderTarget.texture : null;

          loadObjectAndAndEnvMap(); // Add envmap once the texture has been loaded

          texture.dispose();
        }
      );

    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.outputEncoding = THREE.sRGBEncoding;
  }

  var manager = new THREE.LoadingManager(loadModel);

  manager.onProgress = function(item, loaded, total) {
    console.log(item, loaded, total);
  };


  var loader = new THREE.OBJLoader(manager);
  loader.load(
    "https://threejs.org/examples/models/obj/female02/female02.obj",
    function(obj) {
      object = obj;
    }
  );

  //

  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.appendChild(renderer.domElement);

  document.addEventListener("mousemove", onDocumentMouseMove, false);

  //

  window.addEventListener("resize", onWindowResize, false);
}

function onWindowResize() {
  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);
}

function onDocumentMouseMove(event) {
  mouseX = (event.clientX - windowHalfX) / 2;
  mouseY = (event.clientY - windowHalfY) / 2;
}

//

function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  camera.position.x += (mouseX - camera.position.x) * 0.05;
  camera.position.y += (-mouseY - camera.position.y) * 0.05;

  camera.lookAt(scene.position);

  scene.background = exrBackground;
  renderer.toneMappingExposure = 1.0;
  renderer.render(scene, camera);
}
body {
      margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.125.2/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.125.2/examples/js/loaders/OBJLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.125.2/examples/js/loaders/EXRLoader.js"></script>

Please note:

  • The maximum value for roughness and metalness is 1. You have used 2for metalness.
  • Since the sampled value from a roughness map is multiplied with the roughness value from the material, you won't see any effect if you set it to 0. Always start with 1.
Related