简体   繁体   中英

THREE.JS SHADER: Apply color gradient blend to geometry on multiple axes?

Using the information from Apply color gradient to material on mesh - three.js

I was able to create a flower shader that applies the color vertically across the space of the Zinnia. The color blends vertically across the space of the flower from red to yellow, creating a gradient that responds to height. (see image 1)

selection of vertex shader:

      float f = clamp((vPos.z - bbMin.z) / (bbMax.z - bbMin.z), 0., 1.);
      vec3 col = mix(color1, color2, f);
      vec4 diffuseColor = vec4( col, opacity );

selection of fragment shader:

      gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0);

The above code shows that the color is properly responding to a blend taking place on the z-axis.

I was also able to create a flower shader that applies the color from the center of the flower outwards, responding to the Y axis, horizontally. The color is black in the center of the rose, and red on the outer edges. (see image 2)

selection of vertex shader:

      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);

selection of fragment shader:

      gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0);

the above code shows that the color is properly responding to a blend taking place on the y-axis.

(FINALLY:) My question is, how would I combine these two shaders, making the center of the flower blend closer to black? the closer it is to the center while the vertical gradient still exists, The blend from black to red would be happening on the y axis, (or black to transparent, even?) and the blend from red to yellow happening on the z axis? -- I wanted to "darken" the center of the zinnia so that if viewed from profile it doesn't look like a gradient with no definition.

在此处输入图像描述

https://codepen.io/ricky1280/pen/zYWyzQv (shader begins on line 271 in html of this pen)

so that the petals are visible from perfect profile view:

在此处输入图像描述

https://codepen.io/ricky1280/pen/RwMEgmj (shader begins on line 227 of html in this pen)

just for instance this is the red-yellow shader applied on the rose, the gradient is visible from perfect profile在此处输入图像描述

https://codepen.io/ricky1280/pen/dymwRBW (shader begins on line 265 of html in this pen)

(just for instance this is the red-yellow shader applied to the rose, the gradient is visible from profile)

Thank you for reading all of this—I'm lost when I see GLSL, so I hope that someone can help me.

I've made modifications to your fragment shader:

float f = clamp((vPos.z - bbMin.z) / (bbMax.z - bbMin.z), 0., 1.);

// Calculate distance to center of XY plane
float distCenter = length(vPos.xy);

// Re-map values so it converts from [0.0, 0.2] => [0, 1]
distCenter = smoothstep(0.0, 0.2, distCenter);

// Multiplying by 0 makes the color black
// Multiplying by 1 keeps the color at original value
vec3 col = mix(color1, color2, f) * distCenter;

vec4 diffuseColor = vec4( col, opacity );`

Result:

Flower blends to black as fragment approaches the center: 在此处输入图像描述

Play with the 0.2 value inside the smoothstep() to make the gradient wider or narrower. If you've never used length() before, you can read more details on it at the Book of Shaders glossary .

The answer is in your question, if you want to combine those two shaders, then... just combine them:)

在此处输入图像描述

Material will look like this:

    let material = new THREE.MeshBasicMaterial({
      roughness: 1,
      metalness: 0,
      side: THREE.DoubleSide,
      // map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/floors/FloorsCheckerboard_S_Diffuse.jpg", tex => {
      //   tex.wrapS = THREE.RepeatWrapping;
      //   tex.wrapT = THREE.RepeatWrapping;
      //   tex.repeat.set( 16, 1 );
      // }),
      onBeforeCompile: shader => {
        shader.uniforms.bbMin = uniforms.bbMin;
        shader.uniforms.bbMax = uniforms.bbMax;
        shader.uniforms.color1 = uniforms.color1;
        shader.uniforms.color2 = uniforms.color2;
        shader.uniforms.color3 = uniforms.color3;
        shader.vertexShader = `
        varying vec2 vUv;
        varying vec3 vPos;
      ${shader.vertexShader}
    `.replace(
          `#include <begin_vertex>`,
          `#include <begin_vertex>
    vPos = transformed;
    vUv = uv;
    `
        );
        shader.fragmentShader = `
        uniform vec3 bbMin;
      uniform vec3 bbMax;
      uniform vec3 color1;
      uniform vec3 color2;
      uniform vec3 color3;
      varying vec2 vUv;
      varying vec3 vPos;
      ${shader.fragmentShader}
    `.replace(
          `vec4 diffuseColor = vec4( diffuse, opacity );`,
          `
      float f = clamp((vPos.z - bbMin.z) / (bbMax.z - bbMin.z), 0., 1.);
      vec3 col = mix(color1, color2, f);
      col = mix(color3, col, vUv.x);
      vec4 diffuseColor = vec4( col, opacity );`
        );
        //console.log(shader.vertexShader);
        //console.log(shader.fragmentShader);
      }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM