Соотношения сторон - как их использовать? (Настройка окна просмотра D3D) - PullRequest
2 голосов
/ 03 августа 2009

Хорошо - кажется, мой вопрос был таким же облачным, как и моя голова. Попробуем еще раз.

У меня есть 3 свойства при настройке области просмотра для устройства D3D: - Разрешение, в котором работает устройство (в полноэкранном режиме). - Физическое соотношение сторон монитора (как дробь и число с плавающей точкой: 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 (= адаптировано из разрешения устройства), все в порядке, и этот код будет делать то, что от него ожидается. Но как только эти 2 значения перестают быть связанными (например, кто-то запускает разрешение 4: 3 на экране 16:10 с аппаратной растяжкой), требуется другой шаг для компенсации, и у меня возникают проблемы с определением, как именно .

(и p.s Я использую приведение в стиле C на атомарных типах, живите с этим :-))

1 Ответ

3 голосов
/ 04 августа 2009

Я предполагаю, что вы хотите достичь "квадратной" проекции, например когда вы рисуете круг, вы хотите, чтобы он был похож на круг, а не на эллипс.

Единственное, с чем вам следует играть, это соотношение сторон проекции (камеры). В обычных случаях мониторы сохраняют пиксели квадратными, и все, что вам нужно сделать, это установить соотношение сторон вашей камеры, равное соотношению сторон вашего окна просмотра:

viewport_aspect_ratio = viewport_res_x / viewport_res_y;
camera_aspect_ratio = viewport_aspect_ratio;

В растянутом случае, который вы описываете (например, изображение 4: 3, растянутое на экране 16:10), пиксели больше не квадратные, и вы должны учитывать это в соотношении сторон вашей камеры:

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_x и screen_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;
...