title: Morphing in WebGL shaders with mix() between more then two targets
body: <p>I am trying to build an image slider using three.js and am having difficulties with wrapping my head around passing the appropriate state to the glsl shaders so I can transition between the slides. I can easily do it between two targets (be it textures or <a href="https://codepen.io/gbnikolov/pen/LLNOwE?editors=1000" rel="nofollow noreferrer">models</a>) with simply easing between 0 and 1 and passing it as an attrib float like this:</p>
  
  <pre><code>attribute float mix;
  vec4 color = mix(tex1, tex2, mix);
  </code></pre>
  
  <p>But I can't understand how to approach it with more then 2 targets. Should I pass a number and do a bunch of if statements?</p>
  
  <p>I set up my buffer plane geometry and my shader material, which contains my 3 textures, like this:</p>
  
  <pre><code>const uniforms = {
    time: { value: 0 },
    tex1: { type: 't', value: null },
    tex2: { type: 't', value: null },
    tex3: { type: 't', value: null },
    activeTexture: { type: 'i', value: 0 },
    mixFactor:  { value: 0 }
  }
  const vertexShader = document.querySelector('#vertex-shader').text
  const fragmentShader = document.querySelector('#fragment-shader').text
  
  const geometry = new THREE.PlaneBufferGeometry(80, 40, 20, 20)
      const material = new THREE.ShaderMaterial({
      uniforms,
      vertexShader,
      fragmentShader
  })
  
  // textures are loaded here...
  
  // transition using GSAP
  function shift ()  {
      let ease = Power3.easeInOut
      if (counter === 0) {
        TweenMax.to(uniforms.mixFactor, 2, { value: 1, ease, onStart () {
          uniforms.activeTexture.value = 1
        } })
      } else if (counter === 1) {
        TweenMax.to(uniforms.mixFactor, 2, { value: 1, ease, onComplete () {
          uniforms.activeTexture.value = 2
        } })
     } else if (counter === 2) {
        TweenMax.to(uniforms.mixFactor, 2, { value: 2, ease, onComplete () {
          uniforms.activeTexture.value = 0
     } })
  
  
     console.log(uniforms.activeTexture.value)
  
     counter += 1
     if (counter === 3) counter = 0
  }
  
  
  // glsl
  // morph between different targets depending on the passed int attribute
  
  void main () {
    vec4 texColor = vec4(0.0);
    if (activeTexture == 0) {
    texColor = transition(tex1, tex2, vUv, mixFactor);
    } else if (activeTexture == 1) {
      texColor = transition(tex2, tex3, vUv, mixFactor);
    } else if (activeTexture == 2) {
      texColor = transition(tex3, tex1, vUv, mixFactor);
    }
    gl_FragColor = texColor;
  }
  </code></pre>
  
  <p>This doesn't give me the desired effect (the textures abruptly switch between one another, don't transition into place, also it's a bit ugly). I am new to three and am clueless how should I even approach the problem. How does one do this?</p>