D3D中D3DXMatrixPerspectiveFovLH()和D3DXMatrixPerspectiveOffCenterLH()区别及相互转化

本文详细解析了Direct3D中的两种投影矩阵设置方法:D3DXMatrixPerspectiveFovLH()和D3DXMatrixPerspectiveOffCenterLH()。通过实例说明这两种函数的应用场景及如何进行参数转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  在使用Direct3D设置投影矩阵时经常用到下面两个函数:D3DXMatrixPerspectiveFovLH()和D3DXMatrixPerspectiveOffCenterLH(),但是这两个函数究竟有什么区别?他们之间如何转换?这两个问题也是困扰我好久,最近整理了一下网上搜的的资料,下面是本人对这两个函数的理解:D3DXMatrixPerspectiveFovLH()函数是设置整个视椎体,而D3DXMatrixPerspectiveOffCenterLH()函数可以自定义视椎体大小,并且它的参数是在相机空间中度量的,这个函数设置的是视椎体近平面的值。这样说可能很难理解,哈哈。举个例子,这个例子是从网上找到的,参考地址:http://www.cppblog.com/topjackhjj/articles/88219.html

      近日因公司项目需要,写了个屏幕分割渲染的功能。

如下图所示:假设我们有一个场景,场景里面大多数是静态对象(对应图中黑色点),而只有小量的动态对象并且相对集中(对应图中红色点),那么我们在渲染的时候,只要一开始将整个屏幕渲染一次,在后面只更新动态对象所在的区域就可以了。



在测试例子中,我们将整个屏幕分成左右2块,各自分别对应一个投影矩阵和一个视口,他们共用一个视图矩阵和世界矩阵。在如何决定子屏幕所使用的投影矩阵时,主要采用 D3DXMatrixPerspectiveOffCenterLH()或 D3DXMatrixPerspectiveOffCenterRH()这2个函数。具体描述如下:

D3DXMatrixPerspectiveOffCenterLH()
Builds a customized, left-handed perspective projection matrix.

    
D3DXMATRIX * D3DXMatrixPerspectiveOffCenterLH(
        D3DXMATRIX * pOut,
        FLOAT        l,
        FLOAT        r,
        FLOAT        b,
        FLOAT        t,
        FLOAT        zn,
        FLOAT        zf);
  
Parameters
pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
l
[in] Minimum x-value of the view volume.
r
[in] Maximum x-value of the view volume.
b
[in] Minimum y-value of the view volume.
t
[in] Maximum y-value of the view volume.
zn
[in] Minimum z-value of the view volume.
zf
[in] Maximum z-value of the view volume.
Return Values
Pointer to a D3DXMATRIX structure that is a customized, left-handed perspective projection matrix.

Remarks
All the parameters of the D3DXMatrixPerspectiveOffCenterLH function are distances in camera space. The parameters describe the dimensions of the view volume.

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveOffCenterLH function can be used as a parameter for another function.

This function uses the following formula to compute the returned matrix.

2*zn/(r-l)   0            0              0
0            2*zn/(t-b)   0              0
(l+r)/(l-r)  (t+b)/(b-t)  zf/(zf-zn)     1
0            0            zn*zf/(zn-zf)  0

 


D3DXMatrixPerspectiveOffCenterRH()
Builds a customized, right-handed perspective projection matrix.
    
D3DXMATRIX * D3DXMatrixPerspectiveOffCenterRH(
        D3DXMATRIX * pOut,
        FLOAT        l,
        FLOAT        r,
        FLOAT        b,
        FLOAT        t,
        FLOAT        zn,
        FLOAT        zf);
    
  
Parameters
pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
l
[in] Minimum x-value of the view volume.
r
[in] Maximum x-value of the view volume.
b
[in] Minimum y-value of the view volume.
t
[in] Maximum y-value of the view volume.
zn
[in] Minimum z-value of the view volume.
zf
[in] Maximum z-value of the view volume.
Return Values
Pointer to a D3DXMATRIX structure that is a customized, right-handed perspective projection matrix.

Remarks
All the parameters of the D3DXMatrixPerspectiveOffCenterRH function are distances in camera space. The parameters describe the dimensions of the view volume.

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveOffCenterRH function can be used as a parameter for another function.

This function uses the following formula to compute the returned matrix.

2*zn/(r-l)   0            0                0
0            2*zn/(t-b)   0                0
(l+r)/(r-l)  (t+b)/(t-b)  zf/(zn-zf)      -1
0            0            zn*zf/(zn-zf)    0

 

在上述情况下使用D3DXMatrixPerspectiveFovLH()函数是搞不定的,它无法手动指定视椎体大小。只能使用D3DXMatrixPerspectiveOffCenterLH()函数。通过这个例子我们还可以使用D3DXMatrixPerspectiveOffCenterLH()这个函数来做一些效率优化的东西,比如说某些场景无需渲染,可以通过设置视椎体直接卡掉。

 

代码如下(其中纹理文件可以自己替换):

 

  下面说一下这两个矩阵间的转换,只介绍如何将D3DXMatrixPerspectiveFovLH()参数转换成D3DXMatrixPerspectiveOffCenterLH()函数参数,逆过程类似。由上面两个矩阵可以得到如下式子:

xScale=2*zn/(r-l)
ysclae=2*zn/(t-b)
l+r=0
t+b=0

所以,我们可得到:

r=zn/xScale
l=-zn/xScale
t=zn/yScale
b=-zn/yScale

在D3D11中,初始化过程通常包括以下几个关键步骤[^1]: 1. **创建Device**:这是D3D11引擎的核心组件,用于执行图形计算操作。通过`ID3D11CreateDevice`接口创建,可以指定硬件支持级别、多线程模型以及特性水平。 ```cpp IDXGIAdapter* adapter; D3D_FEATURE_LEVEL featureLevel; HRESULT hr = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG, &featureLevel, 1, D3D11_SDK_VERSION, &device, &featureLevel, &context); ``` 2. **创建Context**:与Device一起工作的一个会话上下文,用于提交命令到GPU执行。创建时要关联到Device。 ```cpp ID3D11DeviceContext* context; hr = device->CreateContext(D3D11_CONTEXT_ALL, &context); ``` 3. **深度/模板缓冲渲染目标视图**:设置深度缓冲以存储Z值,渲染目标视图用于最终的图像呈现。这涉及到创建合适的`ID3D11DepthStencilView``ID3D11RenderTargetView`。 ```cpp D3D11_TEXTURE2D_DESC depthDesc; // 初始化深度描述符... HR(device->CreateTexture2D(&depthDesc, NULL, &depthBuffer)); HR(context->CreateDepthStencilView(depthBuffer, ...)); HR(device->CreateRenderTargetView(..., &renderTargetView)); ``` 4. **视口变换矩阵设置**:定义屏幕上的绘制区域投影变换。 ```cpp D3D11_VIEWPORT viewport; viewport.Width = backBufferWidth; viewport.Height = backBufferHeight; // 初始化视口... context->RSSetViewports(1, &viewport); D3DXMATRIX projectionMatrix; D3DXMatrixPerspectiveFovLH(&projectionMatrix, D3DXToRadian(fov), aspectRatio, nearClip, farClip); context->OMSetRenderTargets(1, &renderTargetView, depthBuffer); context->IASetTransformFeedbackLayout(...); ``` 5. **着色器资源管理**:加载并编译着色器程序,配置顶点输入布局几何描述符集,最后绑定资源。 ```cpp ID3DBlob* vertexShaderBlob, *pixelShaderBlob; // 编译着色器... HR(device->CreateVertexShader(vertexShaderBlob, sizeof(vertexShaderBlob), NULL, &vertexShader)); HR(device->CreatePixelShader(pixelShaderBlob, sizeof(pixelShaderBlob), NULL, &pixelShader)); // 绑定资源... context->PSSetShaderResources(0, 1, &shaderResourceView); ``` 完成上述步骤后,D3D11就准备好了进行渲染操作。然而,实际项目可能还需要考虑错误处理、资源清理其他细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值