GLTF/GLB model turns black when using standard material

I’m trying to dynamically update some premade glb files (using an export from Revit).

However, when applying for example some brick materials I found online, which do work on a basic square mesh, the model turns black.

I already added lighting and also tried converting the glb to a jsx file to see if I could achieve it manually, but still no luck.

If I turn on flatshading I do get some color, but the texture cannot be seen.

This is my code:

import {useGLTF, useTexture} from "@react-three/drei";
import THREE, {ClampToEdgeWrapping, Color, DoubleSide, MeshBasicMaterial, MeshStandardMaterial, Texture} from "three";
import React from "react";
import {color} from "three/examples/jsm/nodes/shadernode/ShaderNodeBaseElements";

export default function ModelLoader(props: { fileUrl: string }) {
  const url = props.fileUrl;
  const {nodes, scene, materials} = useGLTF(url, true)

  const paths = [
    'PavingStones092_1K_Color.jpg',
    'PavingStones092_1K_Displacement.jpg',
    'PavingStones092_1K_NormalDX.jpg',
    'PavingStones092_1K_Roughness.jpg',
    'PavingStones092_1K_AmbientOcclusion.jpg',
  ].map(p => '/assets/textures/pave/' + p)

  const [colorMap, displacementMap, normalMap, roughnessMap, aoMap] = useTexture(paths, (texture) => {
    if (texture instanceof Texture) {
      texture.wrapS = texture.wrapT = ClampToEdgeWrapping
      texture.flipY = true
    }
  })
  //


  // console.log(scene, materials)
console.log(nodes)
  console.log(nodes.mesh_2.geometry)

  // map materials
  scene.traverse(o => {
    if (o.type === 'Mesh' && o.material.name === "NLRS_g2_dakpan_donkergrijs") {
        o.material = new MeshStandardMaterial(
          {
            color: "grey",
            normalMap: normalMap,
            map: colorMap,
            flatShading: true,
            roughness: 1,
            roughnessMap: roughnessMap,
            aoMap: aoMap,
            metalness: 0,
            side: DoubleSide,
            emissive: new Color(0.2, 0.2, 0.2),
          }
        )
    }

    // if (o.type === 'Mesh' && o.material.name === "NLRS_g2_baksteen") {
    //   // if (o.type === 'Mesh' && o.material.name !== undefined) {
    //   // o.material = new MeshStandardMaterial()
    //   console.log(o.name)
    //   // o.material.map = colorMap
    //   // o.material.normalMap = normalMap
    //   o.material = brickMaterial
    // }

  })

  // const house = useLoader(GLTFLoader, '/assets/3d/models/b11.gltf')
  // house.scene.traverse(o => {
  //   if (o.type === 'Mesh' && o.material.name === "NLRS_g2_baksteen") {
  //     // if (o.type === 'Mesh' && o.material.name !== undefined) {
  //     // o.material = new MeshStandardMaterial()
  //     console.log(o.name)
  //     // o.material.map = colorMap
  //     // o.material.normalMap = normalMap
  //     o.material = brickMaterial
  //   }
  // })



  return <>

    <primitive object={scene} rotation={[-1 / 2 * Math.PI, 0, 1 / 2 * Math.PI]} scale={1/304.8}/>
    <mesh position={[-5.5, 3, -5.5]}>
      <boxGeometry args={[13, 13, 13]}/>
      <meshStandardMaterial
        map={colorMap}
        // displacementMap={displacementMap}
        // displacementScale={0.01}
        normalMap={normalMap}
        roughnessMap={roughnessMap}
        aoMap={aoMap}
        // flatShading={true}
      />
    </mesh>
  </>
}

Any help or ideas would be much appreciated!

1 Like

When working with a glTF file, use texture.flipY = false. If you have a normal map you might need vertex normals in the mesh too, can’t tell if those are there. It’s also importing to set texture.encoding correctly, either sRGBEncoding for color textures or LinearEncoding for non-color like normal maps.

Hi Don,

Thanks for the reply! (Also great work on all the content you provide on your website!)

I’ve added the encoding in the useTexture like so

  const [colorMap, displacementMap, normalMap, roughnessMap, aoMap] = useTexture(paths, (texture) => {
    if (texture instanceof Texture) {
      texture.wrapS = texture.wrapT = ClampToEdgeWrapping
      texture.flipY = true
      texture.encoding = THREE.sRGBEncoding
    }
  })

But it still gives a black model.

The thing I find interesting is that all this does work for a regular mesh in code, but not for the geometries I’ve exported. Could that be a clue?

Note that they’re not all sRGB — in the list above, only colorMap should be sRGB. The rest contain non-color data and must use LinearEncoding or problems will appear. But I don’t think that’s the cause of the black output.

Most likely the exported geometries do not have normals, or perhaps are missing UVs. Try loading them in https://gltf.report/, open the Metadata tab, and see which mesh attributes are listed?

1 Like

Ah okay thanks for the tip!

I’ve uploaded it, I don’t see anything about normals so that may be the issue then.

Ah I’ve just compared it to a model I found online and indeed the normals are missing!

Thanks for the info so far, I’ll go debug my exporter code.

1 Like