'Why is shader not working on specific models

As a Matrix fan and newbie to three.js/r3f/react/shader, i've decied to try them out with a matrix-like shader.

I've gone through docs and found some sample codes and managed to combine them, here's what i've got: https://codesandbox.io/s/react-fox-matrix-shader-test-g3i4n?file=/src/App.js

import React, { Suspense, useRef } from "react";
import { Canvas, useLoader, useFrame, useThree } from "@react-three/fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import fragmentShader from "./fragment.js";
import vertexShader from "./vertex.js";
import * as THREE from "three";
import { OrbitControls } from "@react-three/drei";

const clock = new THREE.Clock();

const uniforms = {
  u_resolution: { value: { x: window.innerWidth, y: window.innerHeight } },
  u_time: { value: 0.0 }
};

const matrixMaterial = new THREE.ShaderMaterial({
  vertexShader: vertexShader,
  fragmentShader: fragmentShader,
  uniforms
});

const Model = () => {
  const group = useRef();
  const gltf = useLoader(GLTFLoader, "models/scene.gltf"); //Modify to arwing.glb and shader is not working
  const model = gltf.scene;

  model.traverse((m) => {
    if (m instanceof THREE.Mesh) {
      m.material = matrixMaterial;
      m.material.side = THREE.DoubleSide;
    }
  });

  useFrame(() => {
    matrixMaterial.uniforms.u_time.value = clock.getElapsedTime();
    group.current.rotation.y += 0.004;
  });

  return <primitive ref={group} object={model} />;
};

export default function App() {
  const canvasRef = useRef();
  return (
    <>
      <Canvas
        ref={canvasRef}
        style={{ background: "white" }}
        onCreated={({ camera }) => {
          camera.position.set(0, 20, 30);
        }}
      >
        <directionalLight />
        <Suspense fallback={null}>
          <Model />
        </Suspense>
        <OrbitControls />
      </Canvas>
    </>
  );
}

const vertexShader = `
    varying vec2 vUv;

    void main()
    {
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
`;

export default vertexShader;

Yet not all models work if you switch model on l24. What might be the cause? i believe i'm missing some background knowledge on graphics or gltf/glb

Any suggestions on how to debug such issue is appreciated.



Solution 1:[1]

loading the arwing model and changing the shader to just output a color works, so it seems to me the model does not have UV coordinates set up.

You will have to use some sort of 3d editing program to add the appropriate UV coordinates to the model.

Solution 2:[2]

I don't know if this helps, but sometimes a mesh can have multiple materials.

fox example, if you want a box to have different textures on each side, you could have up to 6 materials for 1 mesh.

I would check if the material is an instance of an array and would apply the shader for each material

if (m.material instanceof Array) {
    for (let i = 0; i < m.material.length; i ++) {
        m.material[i] = matrixMaterial;
        m.material[i].side = THREE.DoubleSide;
    }
} else {
    m.material = matrixMaterial;
    m.material.side = THREE.DoubleSide;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 2pha
Solution 2 Naiyo78