【问题标题】:How to make a simple gradient shader on a cube如何在立方体上制作简单的渐变着色器
【发布时间】:2022-01-15 01:59:22
【问题描述】:

我正在尝试使用代码 I found here 根据坐标在立方体上创建渐变着色器。但是我的顶点着色器中的位置似乎没有变化。它从 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')]
      }
    }

【问题讨论】:

  • 我很确定这就是您所需要的:stackoverflow.com/questions/52614371/…
  • 是的,但我有相同的代码,它不会产生渐变,而只会产生两种颜色。这就是我问这个问题的原因
  • 这是一个非常令人困惑的行:vUv.y = position.y;。在我期望的片段着色器中看到vUv,它使用了uv坐标:)

标签: three.js shader


【解决方案1】:

这是使用顶点 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>

【讨论】:

  • 它给出的结果与我已有的相同。立方体只有一半是蓝色的,另一半是红色的。
  • @ZamadhiEturu 我已经更改了 sn-p。在大小为 200 的盒子上盲目地复制粘贴 -1 到 1 范围内的插值代码,你期望会发生什么结果,除了它在视觉上会像颜色之间的硬线?
  • 我不是 three.js 专家(刚刚在 shader 看到这个)但 uniform vec3 colors[2]; uniform float width; varying float h; void main() { float f = h/width + 0.5; f = clamp(f, 0., 1.); gl_FragColor = vec4(mix(colors[0], colors[1], f), 1.0); }const uniforms = { colors: {type: "v3v",value: [new Color("#ff0000"), new Color("#0000ff")]}, width: { type: "float", value: 200.0} 对我有用
  • @Ruzihm 很好:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多