我正在开发一个由两个阶段组成的游戏,其中一个阶段采用正交投影,另一个阶段采用透视投影。
目前,当我们在两种模式之间切换时,会淡入黑色,然后以新的摄像机模式重新出现。
我该如何平滑地过渡到这两种模式之间?
可能有几种方法可以实现这一点,我发现似乎最好的两种方法是:
从一个矩阵到另一个矩阵中所有元素进行线性插值。考虑到所有因素,这个方法似乎相当不错。但我认为这个过渡不会呈现出线性效果,你可以尝试使用缓动函数来代替线性插值。
在透视矩阵上进行dolly zoom,从近0视场跳回正交矩阵,将视野拉出到目标位置,并在过程中大量调整近/远平面。反向操作是将视野插值为0,然后跳回正交矩阵。这个想法的背后是物体在较低的视野下看起来更扁平,而视野为0本质上是一个正交投影。这种方法更加复杂,但也可以进行更多的调整。
proj = lerp(ortho, perspective, 100_000 ** -factor)
。 - undefined#version 150
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix;
uniform float uNearClipPlane = 1.0;
uniform vec2 uPerspToOrtho = vec2( 0.0 );
in vec4 inPosition;
void main( void )
{
// Calculate view space position.
vec4 view = uViewMatrix * uModelMatrix * inPosition;
// Scale x&y to 'undo' perspective projection.
view.x = mix( view.x, view.x * ( -view.z / uNearClipPlane ), uPerspToOrtho.x );
view.y = mix( view.y, view.y * ( -view.z / uNearClipPlane ), uPerspToOrtho.y );
// Output clip space coordinate.
gl_Position = uProjectionMatrix * view;
}
uPerspToOrtho
是一个包含在[0..1]范围内的值的vec2
(例如float2
)。当设置为0时,您的坐标将使用透视投影(假设您的投影矩阵是透视矩阵)。当设置为1时,您的坐标将表现得像是由正交投影矩阵投影而成。您可以为X轴和Y轴单独执行此操作。
NearClipPlane是近剪裁面距离,这是您用于创建透视投影矩阵的值。view.z
而不是-view.z
,但我可能是错的。float zNear = 2.0 * uProjectionMatrix[3][2] / ( 2.0 * uProjectionMatrix[2][2] - 2.0 );
view.xy = mix( view.xy, view.xy * ( -view.z / uNearClipPlane ), uPerspToOrtho.xy );
uniform float uInvNearClipPlane; // = 1.0 / zNear
private double mix(double value1, double value2, double factor)
{
return (value1 * factor) + (value2 * (1 - factor));
}
mix(focalLength/voxel.z, orthoZoom, factor)
在确定焦距和正交缩放因子时,有一个有用的提示:任何距离相机focalLength/orthoZoom
的地方,在整个转换期间都将投影到同一点。
P1(x)
是一个投影中的坐标,而P2(x)
是另一个投影中的坐标,那么你可以通过平滑地从0到1改变f来获得平滑的过渡f P1(x) + (1-f) P2(x)
。 - 463035818_is_not_a_number