GLTF Model roughness/metalness does not work

Hello,

I have a GLTF model that does not look as it should when I import it into my threejs project.
Below you can see three attached videos of the model showcased on different platforms
[BLENDER]

[THREEJS EDITOR]

[CODESANDBOX EDITOR]

The threeJs editor look is what I am trying to achieve, but I am not.

This is the code in the module (modelLoader) that I am using to import the model

import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.145/build/three.module.js";
import { loadingManager, loadedJSONdata, scene, clock } from "../app.js";
import { envMap } from "./environmentLoader.js";

import { GLTFLoader } from "https://cdn.jsdelivr.net/npm/three@0.117/examples/jsm/loaders/GLTFLoader.js";
import { DRACOLoader } from "https://cdn.jsdelivr.net/npm/three@0.117/examples/jsm/loaders/DRACOLoader.js";

export let modelAnimationMixers = [];
export let modelAnimations = [];
export let frontFoam;

let textureLoader = new THREE.TextureLoader();

// video texture playback functionality
let video = document.getElementById("video"); // link video HMTL element to JS
let launchBtn = document.getElementById("launch");
video.play();
launchBtn.addEventListener("launch", function () {
  video.currentTime = 3;
});
let videoTexture = new THREE.VideoTexture(video); // create texture for video

export let FoamAnimMat = new THREE.MeshBasicMaterial({
  alphaMap: videoTexture,
  alphaTest: 0.45,
  side: THREE.DoubleSide,
  fog: false
});

// boat texture maps (override)
let viljanBig_albedo = textureLoader.load(
  "../../images/texture_maps/ViljanBig_albedo.jpg"
);
let viljanBig_light = textureLoader.load(
  "../../images/texture_maps/ViljanBig_light.jpg"
);
let viljanBig_metallic = textureLoader.load(
  "../../images/texture_maps/ViljanBig_metallic.jpg"
);
let viljanBig_roughness = textureLoader.load(
  "../../images/texture_maps/ViljanBig_roughness.jpg"
);
let viljanBig_normal = textureLoader.load(
  "../../images/texture_maps/ViljanBig_normal.jpg"
);

export let topAndBottomMat = new THREE.MeshStandardMaterial({
  map: viljanBig_albedo,
  lightMap: viljanBig_light,
  //metalnessMap: viljanBig_metallic,
  roughnessMap: viljanBig_roughness,
  normalMap: viljanBig_normal,
  fog: false,
  side: THREE.DoubleSide,
  color: 0xffffff,
  metalness: 1,
  roughness: 1,
  flatShading: true,
  wireframe: false
});

export function loadModels() {
  const gltfLoader = new GLTFLoader(loadingManager); // This comes from GLTFLoader.js.
  const dracoLoader = new DRACOLoader(loadingManager);
  // Specify path to a folder containing WASM/JS decoding libraries.
  dracoLoader.setDecoderPath(
    "https://cdn.8thwall.com/web/aframe/draco-decoder/"
  );
  //loader.setDecoderPath('https://unpkg.com/three/examples/js/libs/draco/');

  //loader.setDecoderConfig( { type: 'js' } );
  // Optional: Pre-fetch Draco WASM/JS module.
  dracoLoader.preload();
  gltfLoader.setDRACOLoader(dracoLoader);

  let modelScale;
  const modelFiles = loadedJSONdata.ModelFiles;

  if (loadedJSONdata.ModelScale) {
    modelScale = new THREE.Vector3(
      loadedJSONdata.ModelScale,
      loadedJSONdata.ModelScale,
      loadedJSONdata.ModelScale
    );
  } else {
    modelScale = new THREE.Vector3(1, 1, 1);
  }

  let i = 0;

  function loadModelFile(url) {
    gltfLoader.load(url, (gltf) => {
      const loadedObject = gltf.scene;
      //console.log("loggar loadedObject som " + loadedObject.scale);

      loadedObject.traverse((obj) => {
        //console.log(obj);

        if (obj.isSkinnedMesh) obj.castShadow = true;

        obj.frustumCulled = false;
        if (
          obj.name.includes("glas") ||
          obj.name.includes("Glas") ||
          obj.name.includes("Mesh_112")
        ) {
          obj.material = new THREE.MeshBasicMaterial({
            color: 0x000,
            transparent: true,
            opacity: 0.75,
            side: THREE.DoubleSide,
            depthWrite: false,
            depthTest: true,
            fog: false
            //envMap: envMap
          });

          //console.log("obj is", obj);
          obj.castShadow = false;
          obj.receiveShadow = false;
          obj.renderOrder = 900;
        } else if (
          obj.name.includes("VILJANtop") ||
          obj.name.includes("VILJANbottom")
        ) {
          viljanBig_light.flipY = false;

          obj.material.fog = false;

          obj.material.emissiveIntensity = 0;
          obj.material.flatShading = false;
          obj.material.lightMap = viljanBig_light;
          obj.material.metalness = 1;
          obj.material.roughness = 1;
          //obj.material.dispose();
          //obj.material = topAndBottomMat;
          console.log(obj.name, obj.material);
        } else if (
          obj.name.includes("VILJANgardiner") ||
          obj.name.includes("VILJANinside") ||
          obj.name.includes("VILJANpersienner") ||
          obj.name.includes("VILJANsmall") ||
          obj.name.includes("VILJANtyg")
        ) {
          let newMat = new THREE.MeshStandardMaterial({
            map: obj.material.map,
            lightMap: obj.material.emissiveMap,
            fog: false,
            side: THREE.DoubleSide
          });

          obj.material.dispose();
          obj.material = newMat;
        } else if (obj.name.includes("VILJANflaglow")) {
          //console.log(obj);
          obj.material.emissiveIntensity = 0;
          obj.material.lightMap = obj.material.emissiveMap;
          obj.material.fog = false;
        } else if (obj.name.includes("VILJANproppeller")) {
          let newMat = new THREE.MeshBasicMaterial({
            map: obj.material.map,
            lightMap: obj.material.emissiveMap,
            fog: true,
            side: THREE.DoubleSide,
            envMap: envMap,
            reflectivity: 0.1
          });
          obj.material.lightMap = obj.material.emissiveMap;
          obj.material.dispose();
          obj.material = newMat;
          console.log(obj.material);
        } else if (obj.name.includes("foam_front_short002")) {
          obj.material.fog = false;
          frontFoam = obj;
          frontFoam.material.map.blending = 2;
          frontFoam.material.emissive = { r: 1, g: 1, b: 1 };
          frontFoam.material.emissiveIntensity = 2;
          //console.log("console log 505", obj);
        } else if (obj.name.includes("backfoam_plane")) {
          // console.log("console.log from 507", obj);

          obj.material = FoamAnimMat;

          let objCopy = obj.clone();
          objCopy.position.y = -0.06;
          objCopy.material.flipY = false;
          scene.add(objCopy);
          //obj.fog = false;
          //obj.alphaTest = 1;
          obj.position.y = 0.06;
        }
        obj.castShadow = true;
        obj.receiveShadow = true;
      });

      gltf.animations.forEach((clip) => {
        if (clip.name.indexOf("Camera") > -1) {
        } else {
          //console.log("found model animation: ", clip.name);
          let mixer = new THREE.AnimationMixer(loadedObject);
          modelAnimationMixers.push(mixer);
          mixer.clipAction(clip).loop = THREE.LoopRepeat;
          modelAnimations.push(mixer.clipAction(clip).play());
        }
      });
      loadedObject.scale.set(modelScale.x, modelScale.y, modelScale.z);
      //console.log("loadedObject", loadedObject);
      scene.add(loadedObject);

      if (i < modelFiles.length - 1) {
        // When the model has been loaded and added, load the next one
        i++;
        loadModelFile(modelFiles[i].src);
      }
    });
  }

  //Load first model in array
  loadModelFile(modelFiles[i].src);
}

As you can see I am not altering the material in any way except for connecting the lightmap manually, turning off the fog functionality and other meaningless stuff… etc…

else if (
          obj.name.includes("VILJANtop") ||
          obj.name.includes("VILJANbottom")
        ) {
          viljanBig_light.flipY = false;

          obj.material.fog = false;

          obj.material.emissiveIntensity = 0;
          obj.material.flatShading = false;
          obj.material.lightMap = viljanBig_light;
          obj.material.metalness = 1;
          obj.material.roughness = 1;
          //obj.material.dispose();
          //obj.material = topAndBottomMat;
          console.log(obj.name, obj.material);

Why does my boat look so different?
NOTE*
There is no light source in the scene except from the one that the HDR-image emits.

in blender you have the hdri by default that reflects on metallic surface, u also have to do the same in threejs by loading hdri in the scene.environment

1 Like

Thank you! I assigned it the envMap instead and that was the issue.

1 Like