Resize geometry at window resize

I have a plane geometry with the same aspect ratio than viewport and I want to change its size when viewport size changes.

There is a live example here. The scene has an orbit control, so you can move away the plane with the mouse wheel in order to see the aspect ratio of the plane.

Also, there is a git repo with the code in context.

This is the plane creation:

this.planoProyeccion = new THREE.Mesh(
    new THREE.PlaneGeometry(this.hero.sizes.width * 0.01, this.hero.sizes.height * 0.01),
    new THREE.ShaderMaterial({
        uniforms:
        {
            uTime: { value: 0 },
            uColorStart: { value: new THREE.Color(0xe3e3e3) },
            uColorEnd: { value: new THREE.Color(0xffffff) },
        },
        vertexShader: heroVertexShader,
        fragmentShader: heroFragmentShader,
    })
)
this.scene.add(this.planoProyeccion)

It looks like this:

The scale method works for change the mesh size, but it deforms the material shader. I think, it is because UV remains the same:

resize()
{
    this.planoProyeccion.scale.set( window.innerWidth * 0.01, window.innerHeight * 0.01, 1 );
}

If I resize the viewport, the shader is deformed too:

So, I think, the resizing must act over geometry, not over mesh. I tried this


resize()
{
    this.planoProyeccion.geometry.width = window.innerWidth * 0.01
    this.planoProyeccion.geometry.height = window.innerHeight * 0.01
    this.planoProyeccion.updateMatrix()
    console.log(this.planoProyeccion.geometry.width);
}

But, as can be seen in the live example, it doesn’t work (I don’t know why). How can I do a simple resize for the plane geometry?

this.planoProyeccion.geometry.width = window.innerWidth * 0.01
this.planoProyeccion.geometry.height = window.innerHeight * 0.01

This won’t work, you can’t update the geometry this way, you need to dispose of it and create a new one for each update, wish is less effective and far more expansive then just scaling the mesh.

If you want to fit the plane to the camera viewport you need to create a plane with a height of 1 and width of 1 then scale it relative to the camera Distance/Fov/Aspect.

you can get the plane scale from this method :

function planeFitPerspectiveCamera(plane, camera, relativeZ = null) {
  const cameraZ = relativeZ !== null ? relativeZ : camera.position.z;
  const distance = cameraZ - plane.position.z;
  const vFov = camera.fov * Math.PI / 180;
  const scaleY = 2 * Math.tan(vFov / 2) * distance;
  const scaleX = scaleY * camera.aspect;

  plane.scale.set(scaleX, scaleY, 1);
}

Here is a working example

1 Like