views:

399

answers:

1

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 :-) )

+2  A: 

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;
Luper Rouch
Thanks for answering. Your assumption is partially correct - but I should add to it that I'm also looking to hold on to a certain aspect ratio (or screen format) for the 2D compositioning - much like for ex. a widescreen movie. Unlike a game I hadn't evaluated the option of authoring visuals that'd look good in either proportion.Your hint not to worry about non-square pixels is quite reassuring (was thinking about that), but taking into account the pixel ratio is a good one.
nj
Edited answer to add the "arbitrary viewport aspect ratio on arbitrary screen resolution" stuff.
Luper Rouch
And that about sums up to what the code does now (I realize I didn't paste any code on how I handled my projection aspect ratio, which could've been helpful as that was OK already) :) But fair enough, thanks!
nj
Sorry can't understand what your problem is then. "[...] another step is required to compensate, and I've got trouble figuring out how exactly.": define "compensate".
Luper Rouch
In that snippet, there's a line of code: screen_aspect_ratio = screen_res_x / screen_res_y. This relates the 2. Now what if screen_aspect_ratio is something arbitrary, depicting the physical ratio of the display? (for ex. in case of hardware stretch)(still, the more I discuss this, the more I wonder why I even want this.. - which I guess is good)
nj
screen_aspect_ratio does depict the physical aspect ratio, unless you have non square pixels.
Luper Rouch
Which is the case I wanted to cover. In a config dialog, I'm giving the user the option to either adapt the aspect ratio (from the selected res, obviously) or set it themselves. Hence the possible difference between the 2.
nj
adding to that - I feel this question is hereby answered :) (taking that I might have to look at adjusting my output instead of the res in case of non-square pixels).
nj