代码之家  ›  专栏  ›  技术社区  ›  nielsj

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

  •  2
  • nielsj  · 技术社区  · 15 年前

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

    在为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 ou显示一个Electratio 等于 xres/yres的比率(=根据设备分辨率调整),一切都很好,这段代码将按预期执行。但是,一旦这两个值不再相关(例如,有人在16:10屏幕上运行4:3分辨率,硬件被拉伸),就需要另一个步骤进行补偿,我很难确定具体的补偿方式。

    (P.S我使用C样式的原子类型的强制转换,与之一起使用):-)

    1 回复  |  直到 15 年前
        1
  •  3
  •   Luper Rouch François Lagunas    15 年前

    我假设你想要得到的是一个“正方形”的投影,例如当你画一个圆的时候,你希望它看起来像一个圆而不是椭圆。

    你唯一应该玩的是你的投影(相机)纵横比。通常情况下,监视器保持像素为正方形,您所要做的就是将相机的纵横比设置为与视区的纵横比相等:

    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_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;