如何在立方体上制作简单的渐变着色器

How to make a simple gradient shader on a cube

我正在尝试使用代码 根据坐标在立方体上创建渐变着色器。但是我的顶点着色器中的位置似乎没有变化。它从 0 到 1,中间没有任何步骤:

我做错了什么? https://codesandbox.io/s/modest-silence-xzg1c?file=/src/App.js

这是我的片段和顶点着色器:

    const vertexShader = `
      varying vec2 vUv; 

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

    const fragmentShader = `
      uniform vec3 colors[2]; 

      varying vec2 vUv;

      void main() {
        gl_FragColor = vec4(mix(colors[0], colors[1], vUv.y), 1.0);
      }
    `

    const uniforms = {
      colors: {
        type: 'v3v',
        value: [new Color('#ff0000'), new Color('#0000ff')]
      }
    }

这是使用顶点 Y 坐标插值颜色的方法:

body{
  overflow: hidden;
  margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three@0.135.0";
import {OrbitControls} from "https://cdn.skypack.dev/three@0.135.0/examples/jsm/controls/OrbitControls";

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 10000);
camera.position.set(0, 0, 1500);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

let controls = new OrbitControls(camera, renderer.domElement);

let g = new THREE.BoxBufferGeometry(200, 200, 200, 10, 10, 10);
let m = new THREE.ShaderMaterial({
  uniforms: {
    colors: { 
      value: [new THREE.Color('#ff0000'), new THREE.Color('#0000ff')]
    }
  },
  vertexShader: `
    varying float h; 

    void main() {
      h = position.y;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
  fragmentShader: `
    uniform vec3 colors[2]; 

    varying float h;

    void main() {
      float f = (h + 100.) / 200.;  // linear interpolation
                                // but you can also use 'smoothstep'
      f = clamp(f, 0., 1.);
      gl_FragColor = vec4(mix(colors[0], colors[1], f), 1.0);
    }
  `
})
let o = new THREE.Mesh(g, m);
o.scale.setScalar(5);
scene.add(o);

renderer.setAnimationLoop(() => {
  renderer.render(scene, camera);
});
</script>