首页 > 解决方案 > 对象在屏幕上保持相同大小,无论其与相机的距离如何

问题描述

在 Three.js 中,我有一个远离相机的矩形,如何计算 3D x 和 y 比例以应用于矩形,以便矩形在屏幕上保持相同大小(以像素为单位),无论距离多远从相机它是。

在这里,我制作了一个代码笔,显示矩形远离相机。我希望它在屏幕上保持相同的宽度和高度,无论它在 z 索引中有多远,这意味着矩形的 x 和 y 比例需要根据 z 轴上的距离改变一些比例,这需要根据 z 索引动态发生。

我不知道如何计算这个,我怀疑它的某些函数将以下某些内容作为输入,z 索引偏移,对象的高度或宽度,相机的视野,纵横比,屏幕宽度和高度。最终结果将是物体似乎不会远离相机,即使它正在远离相机。

https://codepen.io/philip368320/pen/bGwJPvE

var width = window.innerWidth;
var height = window.innerHeight;

var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);

var scene = new THREE.Scene();

var cubeGeometry = new THREE.CubeGeometry(100, 100, 0.000001);
var cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
//cube.rotation.y = Math.PI * 45 / 180;
scene.add(cube);


var camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 10000);
camera.position.y = 0;
camera.position.z = 400;
camera.lookAt(cube.position);

scene.add(camera);

var skyboxGeometry = new THREE.CubeGeometry(10000, 10000, 10000);
var skyboxMaterial = new THREE.MeshBasicMaterial({ color: 0x000000, side: THREE.BackSide });
var skybox = new THREE.Mesh(skyboxGeometry, skyboxMaterial);

scene.add(skybox);

var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(0, 300, 200);

scene.add(pointLight);

var clock = new THREE.Clock();

var n = 0;

function render() {
  requestAnimationFrame(render);
  n = n + clock.getDelta() * 30;
  cube.position.z = -n;
  renderer.render(scene, camera);
}

render();

标签: three.js

解决方案


要将立方体保持在您的 codepen 示例中,只需根据距离对其进行缩放。如果它z不在,屏幕上立方体的大小是1/z,所以缩放到它的倒数。

带有缩放的渲染函数(相机和立方体之间的初始距离为400):


    function render() {
      requestAnimationFrame(render);
      n = n + clock.getDelta() * 30;
      cube.position.z = -n;
      cube.scale.set((400+n)/400, (400+n)/400, 1);
      renderer.render(scene, camera);
    }

或者通过计算相机和立方体之间的距离:


    function render() {
      requestAnimationFrame(render);
      n = n + clock.getDelta() * 30;
      cube.position.z = -n;
      let distance = camera.position.distanceTo(cube.position);
      cube.scale.set(distance/400, distance/400, 1);
      renderer.render(scene, camera);
    }

在这里更新了 codepen:https ://codepen.io/mikael-l-nnroth/pen/LYRoaBB


推荐阅读