Mouse movement doesn't appear to be updating fragment shader

Viewed 41

I'm trying to implement the Voronoi shader in the Book of Shaders in three.js and cannot seem to wrap my head around why the mouse position is not having any effect on my visible output. (This is for the initial demo where the mouse moves and the Voronoi updates)

I'm logging the mouse position, checking that the uniform value is updating, yet the shader doesn't appear to be changing whatsoever on my end.

This is what I see (static image - no change at all) while animate is being called.

static voronoi

I'm seeing u_time update when I log it in animate so the callback is happening. The uniforms just don't appear to be updated and I thought I was updating them correctly.

Note - I followed this SO post regarding tracking mouse position as a basis, though I tried both that mouse position and the tweaked mouse I have below (to map from [-1,1]).

Full code:

<!--
  * Based on Book of Shaders 12:
  https://thebookofshaders.com/12/
-->

<!DOCTYPE HTML>
<html>

<head>
  <title>WebGL Demo - Voronoi</title>
  <meta charset="utf-8">
  <style>
    body {
      margin: 0;
      padding: 0;
      overflow: hidden;
    }
  </style>

  <script src="./libraries/threejs/three.min.js"></script>

  <!-- shaders -->
  <script type="x-shader/x-vertex" id="vertexShader">
    void main() {
      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
      gl_Position = projectionMatrix * modelViewPosition;
    }
  </script>
  <script type="x-shader/x-fragment" id="fragmentShader">
    uniform vec2 u_resolution;
    uniform vec2 u_mouse;
    uniform float u_time;

    void main() {
      vec2 st = gl_FragCoord.xy/u_resolution.xy;
      st.x *= u_resolution.x/u_resolution.y;

      vec3 color = vec3(.0);

      // Cell positions
      vec2 point[5];
      point[0] = vec2(0.83,0.75);
      point[1] = vec2(0.60,0.07);
      point[2] = vec2(0.28,0.64);
      point[3] = vec2(0.31,0.26);
      point[4] = u_mouse/u_resolution;

      float m_dist = 1.;  // minimum distance

      // Iterate through the points positions
      for (int i = 0; i < 5; i++) {
          float dist = distance(st, point[i]);

          // Keep the closer distance
          m_dist = min(m_dist, dist);
      }

      // Draw the min distance (distance field)
      color += m_dist;

      // Show isolines
      // color -= step(.7,abs(sin(50.0*m_dist)))*.3;

      gl_FragColor = vec4(color,1.0);
    }
  </script>
</head>

<body></body>

<script>
  let camera, scene, renderer;
  let uniforms, mesh;

  init();
  animate();

  function init() {
    scene = new THREE.Scene();
    camera = new THREE.Camera();
    camera.position.z = 1;

    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setClearColor(0x000000, 1);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(window.devicePixelRatio);
    document.body.appendChild(renderer.domElement);

    uniforms = {
      u_resolution: { type: 'vec2', value: new THREE.Vector2() },
      u_mouse: { type: 'vec2', value: new THREE.Vector2() },
      u_time: { type: 'float', value: 1.0 }
    };

    let vShader = document.getElementById("vertexShader").textContent;
    let fShader = document.getElementById("fragmentShader").textContent;

    let geometry = new THREE.PlaneGeometry(2, 2);

    // give it a material
    let material = new THREE.ShaderMaterial({
      uniforms: uniforms,
      fragmentShader: fShader,
      vertexShader: vShader,
    });

    // and now create the mesh (geom+mat)
    mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    onWindowResize();
    window.addEventListener('resize', onWindowResize, false);
  }

  function animate() {
    requestAnimationFrame(animate);
    render();
  }

  function render() {
    uniforms.u_time.value += 0.05;
    renderer.render(scene, camera);
  }

  function onWindowResize(e) {
    renderer.setSize(window.innerWidth, window.innerHeight);
    uniforms.u_resolution.value.x = renderer.domElement.width;
    uniforms.u_resolution.value.y = renderer.domElement.height;
  }

  document.onmousemove = function (e) {
    uniforms.u_mouse.value.x = (e.clientX / window.innerWidth) * 2 - 1;//e.pageX / window.innerWidth;
    uniforms.u_mouse.value.y = -(e.clientY / window.innerHeight) * 2 + 1;//e.pageY / window.innerHeight;
  }
</script>
</html>
1 Answers

The line point[4] = u_mouse/u_resolution; probably doesn’t need to be divided by u_resolution because the Vector2 is already in the [-1, 1] range. You might just be getting very small values so the mouse movement is indistinguishable.

Related