Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

three.js - Object to retain same size on screen regardless of its distance from the camera

In Three.js I have an rectangle which is moving away from the camera, how can I compute a 3D x and y scale to apply to the rectangle such that the rectangle retains its same size on the screen in pixels, no matter how far away from the camera it is.

Here I made a codepen which shows the rectangle moving away from the camera. I would like it to retain its same width and height on the screen no matter how far away it is in the z index, that means the x and y scale of the rectangle needs to vary by some scale dependent on the distance in the z axis, this needs to occur dynamically dependent on the z index.

I don't know how to compute this, I suspect its some function taking as input some of the following, the z index offset, the height or width of the object, the field of view of the camera, the aspect ratio, the screen width and height. The end result would be that the object would not appear to be moving away from the camera, even though it is moving away.

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();
question from:https://stackoverflow.com/questions/65858400/object-to-retain-same-size-on-screen-regardless-of-its-distance-from-the-camera

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

To keep the cube in place in your codepen example, just scale it according to the distance. If it's z away, the size of the cube on the screen is 1/z, so scale to the inverse of that.

The render function with the scaling (initial distance between the camera and the cube is 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);
    }

Or by calculating the distance between the camera and the cube:


    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);
    }

Updated codepen here: https://codepen.io/mikael-l-nnroth/pen/LYRoaBB


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...