适合 THREE.js 中平面上的比例映射纹理

wsg*_*sgg 1 javascript three.js

我正在尝试在单个平面上“按比例调整”映射的图像纹理。有点模拟 的行为object-fit:cover

因此图像贴图必须按比例放大或缩小才能完全覆盖整个平面。

我尝试尝试纹理的重复和偏移,但没有成功。(在我的代码中注释掉了)

正如您在下面的代码片段中看到的那样,图像仍然可以拉伸以适应。任何帮助表示赞赏!

var renderer = new THREE.WebGLRenderer({ canvas : document.getElementById('canvas'), antialias:true});
    renderer.setClearColor(0x7b7b7b);
    //  use device aspect ratio //
    renderer.setPixelRatio(window.devicePixelRatio);
    // set size of canvas within window 
    renderer.setSize(window.innerWidth, window.innerHeight);

    // SCENE
    var scene = new THREE.Scene();

    // CAMERA
    var camera = new THREE.PerspectiveCamera( 45, window.innerWidth/window.innerHeight, 0.1, 1000 );
    camera.position.z = 5;




    // MESH 0

    // texture
  var texture_0 = new THREE.  TextureLoader().load("https://i.imgur.com/YO0ygMx.jpg");
  texture_0.wrapS = THREE.ClampToEdgeWrapping;
  texture_0.wrapT = THREE.RepeatWrapping;
    // var tileWidth = 2;
    // var tileHeight = 1;
    // repeatX = tileWidth * 1024 / (tileHeight * 2048);
    // repeatY = 1;
    // texture_0.repeat.set(repeatX, repeatY);

    var geometry_0 = new THREE.PlaneGeometry(1.3,1,32);
    var material_0 = new THREE.MeshBasicMaterial({
      color: 0xd8d0d1,
      side: THREE.DoubleSide,
      map: texture_0
    });

    var mesh_0 = new THREE.Mesh(geometry_0, material_0);
    scene.add(mesh_0);

    mesh_0.position.x = -0.7



    // MESH 1

  var texture_1 = new THREE.TextureLoader().load("https://i.imgur.com/YO0ygMx.jpg");
  texture_1.wrapS = THREE.ClampToEdgeWrapping;
  texture_1.wrapT = THREE.RepeatWrapping;


    var geometry_1 = new THREE.PlaneGeometry(1,3,32);
    var material_1 = new THREE.MeshBasicMaterial({
      color: 0xd8d0d1,
      side: THREE.DoubleSide,
      map: texture_1
    });

    var mesh_1 = new THREE.Mesh(geometry_1, material_1);
    scene.add(mesh_1);

    mesh_1.position.x = 0.7


    // RENDER + ANIMATE
    function animate() {
        /* render scene and camera */
        renderer.render(scene,camera);
        requestAnimationFrame(animate);



    }

    requestAnimationFrame(animate);

    // RESIZE EVENTS
    window.addEventListener('resize', onResize);

    function onResize() {
        width = window.innerWidth;
        height = window.innerHeight;
        camera.aspect = width / height;
        camera.updateProjectionMatrix();
        renderer.setSize(width, height);
    }
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r120/three.min.js"></script>
<canvas id="canvas"></canvas>
Run Code Online (Sandbox Code Playgroud)

gma*_*man 5

有很多可能的方面。有纹理本身的方面、平面的大小、平面显示的大小(就像缩放它一样)等等。

不管怎样,至少你需要知道图像的方位和平面的方位。除非您将图像大小硬编码到应用程序中,否则在加载图像之前您不会知道图像的外观。此时,您可以计算正确的偏移量和重复设置,如本文所述

  // Set the repeat and offset properties of the background texture
  // to keep the image's aspect correct.
  const planeAspect = planeWidth / planeHeight;
  const imageAspect = texture.image.width / texture.image.height;
  const aspect = imageAspect / planeAspect;
 
  texture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
  texture.repeat.x = aspect > 1 ? 1 / aspect : 1;
 
  texture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
  texture.repeat.y = aspect > 1 ? 1 : aspect;
Run Code Online (Sandbox Code Playgroud)

  // Set the repeat and offset properties of the background texture
  // to keep the image's aspect correct.
  const planeAspect = planeWidth / planeHeight;
  const imageAspect = texture.image.width / texture.image.height;
  const aspect = imageAspect / planeAspect;
 
  texture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
  texture.repeat.x = aspect > 1 ? 1 / aspect : 1;
 
  texture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
  texture.repeat.y = aspect > 1 ? 1 : aspect;
Run Code Online (Sandbox Code Playgroud)
var renderer = new THREE.WebGLRenderer({ canvas : document.getElementById('canvas'), antialias:true});
    renderer.setClearColor(0x7b7b7b);
    //  use device aspect ratio //
    renderer.setPixelRatio(window.devicePixelRatio);
    // set size of canvas within window 
    renderer.setSize(window.innerWidth, window.innerHeight);

    // SCENE
    var scene = new THREE.Scene();

    // CAMERA
    var camera = new THREE.PerspectiveCamera( 45, window.innerWidth/window.innerHeight, 0.1, 1000 );
    camera.position.z = 5;




  // Set the repeat and offset properties of the background texture
  // to keep the image's aspect correct.
  function fixTexture(planeWidth, planeHeight) {
    return function(texture) {
      const planeAspect = planeWidth / planeHeight;
      const imageAspect = texture.image.width / texture.image.height;
      const aspect = imageAspect / planeAspect;

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

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

    // texture
  var texture_0 = new THREE.  TextureLoader().load("https://i.imgur.com/YO0ygMx.jpg", fixTexture(1.3, 1));
  texture_0.wrapS = THREE.ClampToEdgeWrapping;
  texture_0.wrapT = THREE.RepeatWrapping;
    // var tileWidth = 2;
    // var tileHeight = 1;
    // repeatX = tileWidth * 1024 / (tileHeight * 2048);
    // repeatY = 1;
    // texture_0.repeat.set(repeatX, repeatY);

    var geometry_0 = new THREE.PlaneGeometry(1.3,1,32);
    var material_0 = new THREE.MeshBasicMaterial({
      color: 0xd8d0d1,
      side: THREE.DoubleSide,
      map: texture_0
    });

    var mesh_0 = new THREE.Mesh(geometry_0, material_0);
    scene.add(mesh_0);

    mesh_0.position.x = -0.7



    // MESH 1

  var texture_1 = new THREE.TextureLoader().load("https://i.imgur.com/YO0ygMx.jpg", fixTexture(1,3));
  texture_1.wrapS = THREE.ClampToEdgeWrapping;
  texture_1.wrapT = THREE.RepeatWrapping;


    var geometry_1 = new THREE.PlaneGeometry(1,3,32);
    var material_1 = new THREE.MeshBasicMaterial({
      color: 0xd8d0d1,
      side: THREE.DoubleSide,
      map: texture_1
    });

    var mesh_1 = new THREE.Mesh(geometry_1, material_1);
    scene.add(mesh_1);

    mesh_1.position.x = 0.7


    // RENDER + ANIMATE
    function animate() {
        /* render scene and camera */
        renderer.render(scene,camera);
        requestAnimationFrame(animate);



    }

    requestAnimationFrame(animate);

    // RESIZE EVENTS
    window.addEventListener('resize', onResize);

    function onResize() {
        width = window.innerWidth;
        height = window.innerHeight;
        camera.aspect = width / height;
        camera.updateProjectionMatrix();
        renderer.setSize(width, height);
    }
Run Code Online (Sandbox Code Playgroud)