OBS图形及渲染
+ -

gs_ortho正交投影矩阵

2024-12-13 8 0

在DirectX 11中,正交投影矩阵用于将3D场景投影到2D屏幕上,而不会产生透视效果。正交投影矩阵通常用于2D渲染、UI元素、或需要保持对象相对大小不变的场景。

说人话就是对空间区域进行裁剪投影到2D平现。

https://learn.microsoft.com/zh-cn/windows/win32/api/directxmath/nf-directxmath-xmmatrixorthographicoffcenterrh

https://www.vaczh.com/article/detail-148.html

在Direct3D 11(D3D11)中,默认的投影区间(也称为规范化设备坐标,Normalized Device Coordinates, NDC)通常是 [-1, 1] 范围内的值。
这意味着:

  • X 轴:从 -1 到 1,其中 -1 表示屏幕的最左边,1 表示屏幕的最右边。
  • Y 轴:从 -1 到 1,其中 -1 表示屏幕的最底部,1 表示屏幕的最顶部。
  • Z 轴:从 0 到 1,其中 0 表示最近的裁剪面(近平面),1 表示最远的裁剪面(远平面)。

但实际的坐标不可能为规范化坐标,故需要进行正交投影。

在OBS中,正交投影矩阵使用参数curProjMatrix来表示。其生成方式如下:

void device_ortho(gs_device_t *device, float left, float right, float top, float bottom, float zNear, float zFar)
{
    matrix4 *dst = &device->curProjMatrix;

    float rml = right - left;      // 计算视口宽度
    float bmt = bottom - top;      // 计算视口高度
    float fmn = zFar - zNear;      // 计算近远平面距离差

    // 初始化矩阵为零矩阵
    vec4_zero(&dst->x);
    vec4_zero(&dst->y);
    vec4_zero(&dst->z);
    vec4_zero(&dst->t);

    // 设置矩阵的对角线元素
    dst->x.x = 2.0f / rml;         // X轴缩放因子
    dst->t.x = (left + right) / -rml; // X轴平移因子

    dst->y.y = 2.0f / -bmt;        // Y轴缩放因子(注意这里是负值)
    dst->t.y = (bottom + top) / bmt; // Y轴平移因子

    dst->z.z = 1.0f / fmn;         // Z轴缩放因子
    dst->t.z = zNear / -fmn;       // Z轴平移因子

    dst->t.w = 1.0f;               // 设置w分量为1
}

将{r,l}映射到{-1,1}区间,求{r,l}上位一值在{-1,1}区间的值

150142270103

设三维物体在观察空间中的坐标为Pview,投影矩阵为Mproj,则顶点在投影空间中的坐标为:

Pproj = Pview * Mproj

void gs_device::UpdateViewProjMatrix()
{
    gs_matrix_get(&curViewMatrix);

    /* negate Z col of the view matrix for right-handed coordinate system */
    curViewMatrix.x.z = -curViewMatrix.x.z;
    curViewMatrix.y.z = -curViewMatrix.y.z;
    curViewMatrix.z.z = -curViewMatrix.z.z;
    curViewMatrix.t.z = -curViewMatrix.t.z;

    //相乘 

    matrix4_mul(&curViewProjMatrix, &curViewMatrix, &curProjMatrix);

    //因数据存储的问题,需要转置
    matrix4_transpose(&curViewProjMatrix, &curViewProjMatrix);

    if (curVertexShader->viewProj)
        gs_shader_set_matrix4(curVertexShader->viewProj, &curViewProjMatrix);
}

curViewMatrix这里给出单位矩阵即可。故在着色器中

uniform float4x4 ViewProj;
VertInOut VSDefault(VertInOut vert_in)
{
    VertInOut vert_out;
    vert_out.pos = mul(float4(vert_in.pos.xyz, 1.0), ViewProj);
    vert_out.uv  = vert_in.uv;
    return vert_out;
}

即可将坐标归一下到规范化设备坐标中会坐标显示。

171142237584

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!