在IOS和Android下的纵向和横向模式之间切换时遇到问题。
我可以同时使用人像和风景模式。
我正在使用SDL处理任何方向更改,正在设置相机的新纵横比,并使用新分辨率调用glViewport。在我的情况下,Portrait是640x1136,Landscape是相反的1136x640。
这是我的最终结果,在“肖像”中,模型比“风景”更大。
这是代码的相关部分。
float width = displayMode.w;
float height = displayMode.h;
float aspect = width/height;
m_pCamera->SetAspect(aspect);
glViewport(0, 0, width, height);
while(game->running)
{
while (SDL_PollEvent(&event)) {
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED)
{
width = event.window.data1;
height = event.window.data2;
aspect = width/height;
m_pCamera->SetAspect(aspect);
glViewport(0, 0, width, height);
}
}
最佳答案
透视投影矩阵的常用计算保持了沿y轴显示的几何范围。这正是您的图片所显示的,因此这是标准透视图的预期行为。
为了得到您想要的东西,您需要稍微调整透视矩阵的计算。您可以将与较大屏幕尺寸相对应的轴的范围保持恒定,而不是将y轴上的范围保持恒定。使用此功能,旋转设备时,对象的大小将保持不变。
保持y范围恒定的透视矩阵是这样计算的,tanAng2
是一半视场的tan
,aspRat
是长宽比:
[ 1 / (aspRat * tanAng2) 0 0 0 ]
[ 0 1 / tanAng2 0 0 ]
[ 0 0 (n + f) / (n - f) 2 * n * f / (n - f) ]
[ 0 0 -1 0 ]
在这种情况下,有趣的矩阵元素是
m00
和m11
,因为它们确定x
和y
的缩放比例。关注这两个,并用width / height
替换aspRat
:m00 = height / (width * tanAng2)
m11 = 1 / tanAng2
为了使x范围保持不变,这些矩阵元素的计算公式为:
m00 = 1 / tanAng2
m11 = width / (height * tanAng2)
使用这些值,视野将直接应用于x方向,以前是y方向。此外,
m11 / m00
仍然是aspRat
,这对于避免渲染的几何图形失真是必需的。剩下的就是根据
width
或height
是否更大在两者之间进行选择:if (height > width) {
m00 = height / (width * tanAng2)
m11 = 1 / tanAng2
} else {
m00 = 1 / tanAng2
m11 = width / (height * tanAng2)
}
所有剩余的矩阵元素保持不变,与上面显示的完整矩阵一样。