Texture aspect ratio repeat

I want to make sure that if the width of the canvas is larger than the width of the image, the image is not stretched.
I want the image to repeat, not stretch.
Any help would be appreciated

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
    <title>Three.js - Background - Scene Background Fixed Aspect</title>
    <style>
html, body {
  height: 100%;
  margin: 0;
}
#c {
  width: 100%;
  height: 100%;
  display: block;
}

    </style>
  </head>
  <body>
<canvas id="c"></canvas>
  
  </body>

  <script type="module">
// Three.js - Background - Scene Background Fixed Aspect
// from https://threejsfundamentals.org/threejs/threejs-background-scene-background-fixed-aspect.html

import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r132/build/three.module.js';

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});
  renderer.autoClearColor = false;

  const fov = 75;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 5;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 2;

  const scene = new THREE.Scene();

  {
    const color = 0xFFFFFF;
    const intensity = 1;
    const light = new THREE.DirectionalLight(color, intensity);
    light.position.set(-1, 2, 4);
    scene.add(light);
  }

  const boxWidth = 1;
  const boxHeight = 1;
  const boxDepth = 1;
  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);



  const loader = new THREE.TextureLoader();
  const bgTexture = loader.load('https://threejsfundamentals.org/threejs/resources/images/daikanyama.jpg');
  scene.background = bgTexture;

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render(time) {
    time *= 0.001;

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }

    // Set the repeat and offset properties of the background texture
    // to keep the image's aspect correct.
    // Note the image may not have loaded yet.
    const canvasAspect = canvas.clientWidth / canvas.clientHeight;
    const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;
    const aspect = imageAspect / canvasAspect;

    bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
    bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;

    bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
    bgTexture.repeat.y = aspect > 1 ? 1 : aspect;



    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();

  </script>

</html>

Any reason why you couldn’t just make the canvas transparent (by setting alpha: true in the WebGLRenderer constructor) and just applying the background with CSS?

You can do it with WebGL, but it’ll be a bit more complicated than using CSS in this case - as you’d need a small, custom shader, or a viewport-covering plane mesh.

[quote=“mjurczyk, post:2, topic:60591”]
Any reason why you couldn’t just make the canvas transparent (by setting alpha: true in the WebGLRenderer constructor) and just applying the background with CSS?

You can do it with WebGL, but it’ll be a bit more complicated than using CSS in this case - as you’d need a small, custom shader, or a viewport-covering plane
[/Yes, I need to implement it in the form above using three.js. In the source code attached above, if the size of the canvas width exceeds the image size, the image is not stretched, but the image is repeated, so that one image appears completely and the end of the image is expanded in the remaining part.

Just because I didn’t see it in your code, and also with no context because I haven’t read the thread…
make sure texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
the default is ClampToEdgeWrapping. hth