Search code examples
javascriptthree.jsglslshader

Problem on changing scale of vUv in custom shader for three.js: the smaller the number to multipy is, the bigger the result paint appears


I'm trying to use custom shader for three.js to make a single texture animate and expand. The problem here is, when I multiply vUv with certain number to make it expand, the bigger the number is, the smaller the result paint appears, which means it works contrary to my expectation. For example, when I multiply 0.1, the result becomes 10 times bigger, and when I multiply 10.0, it becomes 10 times smaller.

Here is my shader codes (simplified to make the problem clear):

//vertex shader

varying vec2 vUv;

uniform float uFixAspect;

void main() {
  vUv = uv;

  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
precision mediump float;
uniform float time;
uniform vec2 resolution;

varying vec2 vUv;

uniform sampler2D uTex;

void main() {

  // I want the result to be 10 times smaller than original, but it draws 10 times bigger than original
  mat2 newvUv = vUv * mat2(0.1, 0.0, 0.0, 0.1);
  gl_FragColor= texture2D(uTex, newvUv);

}

and, this is my three.js code:

      const loader = new THREE.TextureLoader();
      loader.load(
        "./assets/textures/tex.png",
        tex => {
          const geo = new THREE.PlaneGeometry(2, 2);
          const mat = new THREE.ShaderMaterial({
            uniforms: {
              uTex: {
                value: tex
              },
              time: {
                type: "f",
                value: 0.1
              },
              resolution: {
                type: "vec2",
                value: new THREE.Vector2(512, 512)
              }
            },
            vertexShader: vert,
            fragmentShader: frag,
          });

          const shaderObj = new THREE.Mesh(
            geo,
            mat
          );

          marker.add(shaderObj);
        }
      );

Is there any problem on my code or is it the problem of three.js? Thank you.


Solution

  • [...] when I multiply vUv with certain number to make it expand, the bigger the number is, the smaller the result paint appears [...]

    Of course, because you scale the texture coordinates for the look up, but not the texture.
    You want to "scale down" the texture. The texture keeps the same size, so you've to take the texels form a "up scaled" position.

    Use the reciprocal of the scale factor:

    float scale = 1.0/0.1; // reciprocal scale
    mat2 newvUv = vUv * mat2(scale, 0.0, 0.0, scale);