长宽比 - 如何处理它们? (D3D 视口设置)

发布于 2024-07-30 04:26:45 字数 1250 浏览 4 评论 0原文

好吧——看来我的问题和我的头脑一样模糊。 让我们再试一次。

在为 D3D 设备配置视口时,我有 3 个属性: - 设备运行时的分辨率(全屏)。 - 显示器的物理纵横比(分数和浮点数:1,例如 4:3 和 1.33)。 - 源分辨率的宽高比(源分辨率本身没有任何意义,它只告诉我们渲染所需的宽高比以及最适合运行的分辨率类型)。

然后我们遇到这个:

// -- figure out aspect ratio adjusted VPs  -- 

m_nativeVP.Width = xRes;
m_nativeVP.Height = yRes;
m_nativeVP.X = 0;
m_nativeVP.Y = 0;
m_nativeVP.MaxZ = 1.f;
m_nativeVP.MinZ = 0.f;

FIX_ME // this does not cover all bases -- fix!
uint xResAdj, yResAdj;  
if (g_displayAspectRatio.Get() < g_renderAspectRatio.Get())
{
    xResAdj = xRes;
    yResAdj = (uint) ((float) xRes / g_renderAspectRatio.Get());
}
else if (g_displayAspectRatio.Get() > g_renderAspectRatio.Get())
{
    xResAdj = (uint) ((float) yRes * g_renderAspectRatio.Get());
    yResAdj = yRes;     
}
else // ==
{
    xResAdj = xRes;
    yResAdj = yRes;
}

m_fullVP.Width = xResAdj;
m_fullVP.Height = yResAdj;
m_fullVP.X = (xRes - xResAdj) >> 1; 
m_fullVP.Y = (yRes - yResAdj) >> 1; 
m_fullVP.MaxZ = 1.f;
m_fullVP.MinZ = 0.f;

现在只要 g_displayAspectRatio 等于 xRes/yRes 的比率(= 根据设备分辨率调整),一切都很好,并且此代码将执行预期的操作。 但是一旦这两个值不再相关(例如,有人在 16:10 的屏幕上运行 4:3 的分辨率,硬件拉伸),就需要另一个步骤来补偿,而且我很难弄清楚到底如何。

(ps我在原子类型上使用C风格的转换,接受它:-))

Allright - seems my question was as cloudy as my head. Lets try again.

I have 3 properties while configuring viewports for a D3D device:
- The resolution the device is running in (full-screen).
- The physical aspect ratio of the monitor (as fraction and float:1, so for ex. 4:3 & 1.33).
- The aspect ratio of the source resolution (source resolution itself is kind of moot and tells us little more than the aspect ratio the rendering wants and the kind of resolution that would be ideal to run in).

Then we run into this:

// -- figure out aspect ratio adjusted VPs  -- 

m_nativeVP.Width = xRes;
m_nativeVP.Height = yRes;
m_nativeVP.X = 0;
m_nativeVP.Y = 0;
m_nativeVP.MaxZ = 1.f;
m_nativeVP.MinZ = 0.f;

FIX_ME // this does not cover all bases -- fix!
uint xResAdj, yResAdj;  
if (g_displayAspectRatio.Get() < g_renderAspectRatio.Get())
{
    xResAdj = xRes;
    yResAdj = (uint) ((float) xRes / g_renderAspectRatio.Get());
}
else if (g_displayAspectRatio.Get() > g_renderAspectRatio.Get())
{
    xResAdj = (uint) ((float) yRes * g_renderAspectRatio.Get());
    yResAdj = yRes;     
}
else // ==
{
    xResAdj = xRes;
    yResAdj = yRes;
}

m_fullVP.Width = xResAdj;
m_fullVP.Height = yResAdj;
m_fullVP.X = (xRes - xResAdj) >> 1; 
m_fullVP.Y = (yRes - yResAdj) >> 1; 
m_fullVP.MaxZ = 1.f;
m_fullVP.MinZ = 0.f;

Now as long as g_displayAspectRatio equals the ratio of xRes/yRes (= adapted from device resolution), all is well and this code will do what's expected of it. But as soon as those 2 values are no longer related (for example, someone runs a 4:3 resolution on a 16:10 screen, hardware-stretched) another step is required to compensate, and I've got trouble figuring out how exactly.

(and p.s I use C-style casts on atomic types, live with it :-) )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一影成城 2024-08-06 04:26:45

我假设您想要实现的是“方形”投影,例如,当您绘制圆形时,您希望它看起来像圆形而不是椭圆形。

您唯一应该考虑的是您的投影(相机)纵横比。 在正常情况下,显示器保持像素正方形,您所要做的就是将相机宽高比设置为等于视口的宽高比:

viewport_aspect_ratio = viewport_res_x / viewport_res_y;
camera_aspect_ratio = viewport_aspect_ratio;

在您描述的拉伸情况下(例如,在 16:10 屏幕上拉伸 4:3 图像),像素不再是方形的,您必须在相机宽高比中考虑到这一点:

stretch_factor_x = screen_size_x / viewport_res_x;
stretch_factor_y = screen_size_y / viewport_res_y;
pixel_aspect_ratio = stretch_factor_x / stretch_factor_y;
viewport_aspect_ratio = viewport_res_x / viewport_res_y;
camera_aspect_ratio = viewport_aspect_ratio * pixel_aspect_ratio;

其中 screen_size_xscreen_size_y 是显示器实际尺寸的倍数(例如 16:10 )。

但是,您应该简单地假设正方形像素(除非您有特定的理由不这样做),因为显示器可能会向系统报告不正确的物理尺寸信息,或者根本不报告任何信息。 此外,显示器并不总是会拉伸,例如我的显示器保持 1:1 像素长宽比,并为较低的分辨率添加黑色边框。

编辑

如果您想将视口调整为某种纵横比并使其适应任意分辨率,那么您可以这样做:

viewport_aspect_ratio = 16.0 / 10.0; // The aspect ratio you want your viewport to have
screen_aspect_ratio = screen_res_x / screen_res_y;

if (viewport_aspect_ratio > screen_aspect_ratio) {
    // Viewport is wider than screen, fit on X
    viewport_res_x = screen_res_x;
    viewport_res_y = viewport_res_x / viewport_aspect_ratio;
} else {
    // Screen is wider than viewport, fit on Y
    viewport_res_y = screen_res_y;
    viewport_res_x = viewport_res_y * viewport_aspect_ratio;
}

camera_aspect_ratio = viewport_res_x / viewport_res_y;

I'm assuming what you want to achieve is a "square" projection, e.g. when you draw a circle you want it to look like a circle rather than an ellipse.

The only thing you should play with is your projection (camera) aspect ratio. In normal cases, monitors keep pixels square and all you have to do is set your camera aspect ratio equal to your viewport's aspect ratio:

viewport_aspect_ratio = viewport_res_x / viewport_res_y;
camera_aspect_ratio = viewport_aspect_ratio;

In the stretched case you describe (4:3 image stretched on a 16:10 screen for example), pixels are not square anymore and you have to take that into account in your camera aspect ratio:

stretch_factor_x = screen_size_x / viewport_res_x;
stretch_factor_y = screen_size_y / viewport_res_y;
pixel_aspect_ratio = stretch_factor_x / stretch_factor_y;
viewport_aspect_ratio = viewport_res_x / viewport_res_y;
camera_aspect_ratio = viewport_aspect_ratio * pixel_aspect_ratio;

Where screen_size_x and screen_size_y are multiples of the real size of the monitor (e.g. 16:10).

However, you should simply assume square pixels (unless you have a specific reason no to), as the monitor may report incorrect physical size informations to the system, or no informations at all. Also monitors don't always stretch, mine for example keeps 1:1 pixels aspect ratio and adds black borders for lower resolutions.

Edit

If you want to adjust your viewport to some aspect ratio and fit it on an arbitrary resolution then you could do like that :

viewport_aspect_ratio = 16.0 / 10.0; // The aspect ratio you want your viewport to have
screen_aspect_ratio = screen_res_x / screen_res_y;

if (viewport_aspect_ratio > screen_aspect_ratio) {
    // Viewport is wider than screen, fit on X
    viewport_res_x = screen_res_x;
    viewport_res_y = viewport_res_x / viewport_aspect_ratio;
} else {
    // Screen is wider than viewport, fit on Y
    viewport_res_y = screen_res_y;
    viewport_res_x = viewport_res_y * viewport_aspect_ratio;
}

camera_aspect_ratio = viewport_res_x / viewport_res_y;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文