three.js 如何在不拉伸前景的情况下增加视角
How to increase perspective without stretching foreground in three.js
我有一个 three.js 场景,其中有带纹理的地板平面,需要非常特定的视角才能与静态 2D 叠加层对齐
我的问题是,我越是增加相机 FOV 以获得我需要的视角,前景就越伸展,但我不希望这样。我似乎需要一个非常高的 FOV (~ 120 - 150) 来使纹理跟随墙壁,而且它是如此之高以至于相机正在渲染位于它后面的东西。我需要将相机几乎移动到场景的中心才能显示整个楼层,这感觉不对。我怎样才能调整这个场景以获得正确的视角而不失真?
实例:http://warriorhut.net/testing/shapes/backend/room/view.basic.php
相关的相机设置是:
var WIDTH = 1024;
var HEIGHT = 683;
var FOV = 140; // Increases perspective as it goes higher but also distortion
camera = new THREE.PerspectiveCamera(FOV, WIDTH/HEIGHT, .1, 3000);
camera.position.x = 0;
camera.position.y = 200;
camera.position.z = 0;
//camera.lookAt(scene.position);
camera.lookAt(new THREE.Vector3( 0, 100, -400 )); // look at the back of the room
camera.updateProjectionMatrix();
通过反复试验解决。解决方案是增加相机向上倾斜以增加距离衰减而不是增加 FOV
var FOV = 100;
camera.position.x = -100;
camera.position.y = 540;
camera.position.z = 3500; // Moved further back
//camera.lookAt(scene.position);
camera.lookAt(new THREE.Vector3( 0, 590, -1000 )); // look at the back of the room AND TILT UPWARDS!
恕我直言,这些固定数字看起来很糟糕,有时您的代码无法处理(现在可能正在处理这种情况,您为什么不尝试通用 lookAt 方法。意味着这是通用问题 Open GL 有三个与相机 lookAt 的争论。
眼睛、中心和颠倒的矢量。
更多地玩 FOV 不是一个好的选择。
我在 Webgl 上玩游戏,我所做的就是将相机放在物体后面 http://stemkoski.github.io/Three.js/Chase-Camera.html
可能这个 link 有用。
如果没有,那么您可以制作通用解决方案,例如:
if(typeof fc == "undefined") fc=0;
var delta =0.02;
var y=object.rotation.y;
var dir=object.rotation.y-fc;
var fc = THREE.Math.clamp( fc + 2 * delta * dir, y-control.followRadius, y+control.followRadius );
var sn = Math.sin( fc);
var cs = Math.cos(fc);
camera.rotation.set(0,0,0);
camera.position.x=object.position.x+(control.positionOffsetZ*sn);
camera.position.y=object.position.y+control.positionOffsetY;
camera.position.z=object.position.z+(control.positionOffsetZ*cs);
camera.lookAt(new THREE.Vector3(
object.position.x+(control.targetOffsetZ*sn)
,object.position.y+control.targetOffsetY
,object.position.z+(control.targetOffsetZ*cs)
));
var control = {"positionOffsetZ":-39,"positionOffsetY":3.2,"targetOffsetZ":5,"targetOffsetY":0,"followRadius":0.35
});
请考虑 "object" 是虚拟的隐形立方体,您的相机连接在其上,您正在使用按键控制移动它。
您可以直接将此代码片段粘贴到您的 wirk 和 things wirk 中。如有任何问题或疑问,请随时提出。
向现有图像添加虚拟 object 需要尽可能匹配原始相机参数。在这种情况下,因为图像是合成的,理想情况下,您将从生成它的人那里获得这些参数。否则我们可以尝试通过对图像进行测量来推断一些参数。
我将做出 pinhole camera, and further assume that the optical axis is at the center of the image. Parallel lines in the scene will meet at a vanishing point 的标准假设。在此图像中,我们只能以任意精度确定一个消失点:
这里的平行线也平行于地平面,也就是说消失点在horizon上。 horizon 因此略低于此图像的中心,这意味着相机略微向上倾斜。
向上多少?消失点位于图像中心下方约 0.022 个图像高度(15 像素)处。我们可以用垂直视野来表示指示的相机俯仰:
pitch = arctan(2 * tan(vfov/2) * 0.022)
我们可以类似地确定相机相对于平行线的偏航。消失点位于中心右侧约 0.010 图像高度处,因此相机略微向左偏转。
yaw = arctan(2 * tan(vfov/2) * -0.010)
为了在 three.js 应用程序中表达这一点,我修改了代码的相机配置部分,如下所示:
var FOV = 75;
[...]
camera.position.x = 0;
camera.position.y = 200;
camera.position.z = 512;
var lookTarget = new THREE.Vector3().copy(camera.position);
var tanScale = 2 * Math.tan(FOV/2 * Math.PI/180);
lookTarget.x += -0.010 * tanScale;
lookTarget.y += 0.022 * tanScale;
lookTarget.z += -1;
camera.lookAt(lookTarget);
camera.updateProjectionMatrix();
我将相机向后(朝向正 Z)移动了一点以使大部分地板几何体可见(这不会改变渲染几何体的消失点)。然后我把FOV
改成了75度(还是挺广角的),纹理图案现在自动收敛到消失点,少了很多perspective distortion:
请注意,您现在可以看到地板几何图形的末端,因为假设视野较小会增加图像的假设深度,因此您可能需要增加地板的尺寸。您可以修改视野以调整纹理透视缩短,并且相机代码应将消失点保持在同一位置。我认为这张特定图像中没有足够的特征让我们估计它的实际焦距,但它可能在其他图像中是可能的 - 在这种情况下我们也可以推断出视野。
我有一个 three.js 场景,其中有带纹理的地板平面,需要非常特定的视角才能与静态 2D 叠加层对齐
我的问题是,我越是增加相机 FOV 以获得我需要的视角,前景就越伸展,但我不希望这样。我似乎需要一个非常高的 FOV (~ 120 - 150) 来使纹理跟随墙壁,而且它是如此之高以至于相机正在渲染位于它后面的东西。我需要将相机几乎移动到场景的中心才能显示整个楼层,这感觉不对。我怎样才能调整这个场景以获得正确的视角而不失真?
实例:http://warriorhut.net/testing/shapes/backend/room/view.basic.php
相关的相机设置是:
var WIDTH = 1024;
var HEIGHT = 683;
var FOV = 140; // Increases perspective as it goes higher but also distortion
camera = new THREE.PerspectiveCamera(FOV, WIDTH/HEIGHT, .1, 3000);
camera.position.x = 0;
camera.position.y = 200;
camera.position.z = 0;
//camera.lookAt(scene.position);
camera.lookAt(new THREE.Vector3( 0, 100, -400 )); // look at the back of the room
camera.updateProjectionMatrix();
通过反复试验解决。解决方案是增加相机向上倾斜以增加距离衰减而不是增加 FOV
var FOV = 100;
camera.position.x = -100;
camera.position.y = 540;
camera.position.z = 3500; // Moved further back
//camera.lookAt(scene.position);
camera.lookAt(new THREE.Vector3( 0, 590, -1000 )); // look at the back of the room AND TILT UPWARDS!
恕我直言,这些固定数字看起来很糟糕,有时您的代码无法处理(现在可能正在处理这种情况,您为什么不尝试通用 lookAt 方法。意味着这是通用问题 Open GL 有三个与相机 lookAt 的争论。 眼睛、中心和颠倒的矢量。 更多地玩 FOV 不是一个好的选择。
我在 Webgl 上玩游戏,我所做的就是将相机放在物体后面 http://stemkoski.github.io/Three.js/Chase-Camera.html 可能这个 link 有用。
如果没有,那么您可以制作通用解决方案,例如:
if(typeof fc == "undefined") fc=0;
var delta =0.02;
var y=object.rotation.y;
var dir=object.rotation.y-fc;
var fc = THREE.Math.clamp( fc + 2 * delta * dir, y-control.followRadius, y+control.followRadius );
var sn = Math.sin( fc);
var cs = Math.cos(fc);
camera.rotation.set(0,0,0);
camera.position.x=object.position.x+(control.positionOffsetZ*sn);
camera.position.y=object.position.y+control.positionOffsetY;
camera.position.z=object.position.z+(control.positionOffsetZ*cs);
camera.lookAt(new THREE.Vector3(
object.position.x+(control.targetOffsetZ*sn)
,object.position.y+control.targetOffsetY
,object.position.z+(control.targetOffsetZ*cs)
));
var control = {"positionOffsetZ":-39,"positionOffsetY":3.2,"targetOffsetZ":5,"targetOffsetY":0,"followRadius":0.35
});
请考虑 "object" 是虚拟的隐形立方体,您的相机连接在其上,您正在使用按键控制移动它。 您可以直接将此代码片段粘贴到您的 wirk 和 things wirk 中。如有任何问题或疑问,请随时提出。
向现有图像添加虚拟 object 需要尽可能匹配原始相机参数。在这种情况下,因为图像是合成的,理想情况下,您将从生成它的人那里获得这些参数。否则我们可以尝试通过对图像进行测量来推断一些参数。
我将做出 pinhole camera, and further assume that the optical axis is at the center of the image. Parallel lines in the scene will meet at a vanishing point 的标准假设。在此图像中,我们只能以任意精度确定一个消失点:
这里的平行线也平行于地平面,也就是说消失点在horizon上。 horizon 因此略低于此图像的中心,这意味着相机略微向上倾斜。
向上多少?消失点位于图像中心下方约 0.022 个图像高度(15 像素)处。我们可以用垂直视野来表示指示的相机俯仰:
pitch = arctan(2 * tan(vfov/2) * 0.022)
我们可以类似地确定相机相对于平行线的偏航。消失点位于中心右侧约 0.010 图像高度处,因此相机略微向左偏转。
yaw = arctan(2 * tan(vfov/2) * -0.010)
为了在 three.js 应用程序中表达这一点,我修改了代码的相机配置部分,如下所示:
var FOV = 75;
[...]
camera.position.x = 0;
camera.position.y = 200;
camera.position.z = 512;
var lookTarget = new THREE.Vector3().copy(camera.position);
var tanScale = 2 * Math.tan(FOV/2 * Math.PI/180);
lookTarget.x += -0.010 * tanScale;
lookTarget.y += 0.022 * tanScale;
lookTarget.z += -1;
camera.lookAt(lookTarget);
camera.updateProjectionMatrix();
我将相机向后(朝向正 Z)移动了一点以使大部分地板几何体可见(这不会改变渲染几何体的消失点)。然后我把FOV
改成了75度(还是挺广角的),纹理图案现在自动收敛到消失点,少了很多perspective distortion:
请注意,您现在可以看到地板几何图形的末端,因为假设视野较小会增加图像的假设深度,因此您可能需要增加地板的尺寸。您可以修改视野以调整纹理透视缩短,并且相机代码应将消失点保持在同一位置。我认为这张特定图像中没有足够的特征让我们估计它的实际焦距,但它可能在其他图像中是可能的 - 在这种情况下我们也可以推断出视野。