为什么着色器不适用于特定的模型



作为《黑客帝国》的粉丝和three.js/r3f/react/shader的新手,我决定用类似矩阵的着色器来尝试它们。

我浏览了文档,找到了一些示例代码,并设法将它们组合在一起,以下是我所得到的: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;

然而,若在l24上切换模型,并不是所有的模型都能工作。原因可能是什么?我想我错过了一些关于图形或gltf/glb 的背景知识

任何关于如何调试此类问题的建议都将不胜感激。

加载arwing模型并更改着色器以仅输出颜色是可行的,所以在我看来,该模型没有设置UV坐标。

您将不得不使用某种三维编辑程序来向模型添加适当的UV坐标。

我不知道这是否有帮助,但有时一个网格可以有多种材质。

例如,如果你想让一个盒子的每一面都有不同的纹理,那么一个网格最多可以有6种材质。

我会检查材质是否是数组的实例,并为每个材质应用着色器

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;
}

最新更新