Adreno GPU上从 OpenGL ES 迁移到 Direct3D11.1介绍 (4)

Adreno GPU上从 OpenGL ES 迁移到 Direct3D11.1介绍 (4)

6.2.5 Framebuffer对象

在OpenGL ES中,渲染目标是使用Framebuffer对象(FBOs)创建的。FBOs有附着点用于颜色缓冲(如果使用多个渲染目标,则不止一个)和深度/模板缓冲(深度和模板可以分开或结合在一个交错缓冲中)。下面的代码块演示了创建一个FBO的颜色附件,可以用作纹理和深度/模板附件,可以作为纹理获取。

    glGenTextures( 1, &m_hTexture );
    glBindTexture( GL_TEXTURE_2D, m_hTexture );
    glTexImage2D( GL_TEXTURE_2D, 0, nInternalFormat, nWidth, nHeight, 0, nFormat, 
    nType, NULL );
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 
    m_hTexture, 0 );
    glGenTextures( 1, &m_hDepthTexture);
    glBindTexture( GL_TEXTURE_2D, m_hDepthTexture);
    glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, nWidth, nHeight, 0, 
    GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL );
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 
    m_hDepthTexture, 0);
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 
    m_hDepthTexture, 0);

为了在Direct3D11中创建一个可以作为纹理的渲染目标,我们需要创建一个带有着色器资源视图和渲染目标视图的纹理。下面的代码块演示了如何创建一个具有纹理颜色缓冲和深度/模板缓冲的渲染目标。

    D3D11_TEXTURE2D_DESC textureDesc; 
    ZeroMemory( &textureDesc, sizeof(textureDesc) );
    textureDesc.Width = nWidth;
    textureDesc.Height = nHeight;
    textureDesc.MipLevels = 1;
    textureDesc.ArraySize = 1;
    textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    textureDesc.SampleDesc.Count = 1;
    textureDesc.Usage = D3D11_USAGE_DEFAULT;
    textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
    textureDesc.CPUAccessFlags = 0;
    textureDesc.MiscFlags = 0;

    // Render target view
    D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
    ZeroMemory(&renderTargetViewDesc, sizeof(renderTargetViewDesc));
    renderTargetViewDesc.Format = textureDesc.Format;
    renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
    renderTargetViewDesc.Texture2D.MipSlice = 0;

    // Shader resource view
    D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
    ZeroMemory(&shaderResourceViewDesc, sizeof(shaderResourceViewDesc));
    shaderResourceViewDesc.Format = textureDesc.Format;
    shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    shaderResourceViewDesc.Texture2D.MipLevels = 1;
    shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;

    // Sampler description
    D3D11_SAMPLER_DESC samplerDesc;
    ZeroMemory(&samplerDesc, sizeof(samplerDesc));
    samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
    samplerDesc.MaxAnisotropy = 0;
    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
    samplerDesc.MipLODBias = 0.0f;
    samplerDesc.MinLOD = 0;
    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
    samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    samplerDesc.BorderColor[0] = 0.0f;
    samplerDesc.BorderColor[1] = 0.0f;
    samplerDesc.BorderColor[2] = 0.0f;
    samplerDesc.BorderColor[3] = 0.0f;
    
    // Create Texture 
    ComPtr<ID3D11Texture2D> pTexture;
    if ( FAILED(pD3DDevice->CreateTexture2D( &textureDesc, NULL, &pTexture) ) )
    {
        return FALSE;
    }

    // Create Render Target View 
    ComPtr<ID3D11RenderTargetView> pTextureRenderTargetView;
    if ( FAILED(pD3DDevice->CreateRenderTargetView( pTexture.Get(), 
    &renderTargetViewDesc,&pTextureRenderTargetView ) ) )
    {
        return FALSE;
    }

    // Create Shader Resource View
    ComPtr<ID3D11ShaderResourceView> pTextureShaderResourceView;
    if ( FAILED(pD3DDevice->CreateShaderResourceView( pTexture.Get(),
    &shaderResourceViewDesc,&pTextureShaderResourceView) ) )
    {
        return FALSE;
    }

    // Create Sampler State
    ComPtr<ID3D11SamplerState> pTextureSampler;
    if ( FAILED(pD3DDevice->CreateSamplerState( &samplerDesc, &pTextureSampler ) ) )
    {
        return FALSE;
    }

    // Create a depth/stencil texture for the depth attachment
    ComPtr<ID3D11Texture2D> pDepthTexture; 
    textureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    textureDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    if ( FAILED(pD3DDevice->CreateTexture2D( &textureDesc, NULL, &pDepthTexture )))
        return FALSE;
    
    ComPtr<ID3D11DepthStencilView> pDepthStencilView;
    D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
    ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
    depthStencilViewDesc.Format = textureDesc.Format;
    depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    depthStencilViewDesc.Texture2D.MipSlice = 0;
    if ( FAILED(pD3DDevice ->CreateDepthStencilView( pDepthTexture.Get(), &depthStencilViewDesc, &pDepthStencilView ) ) )
        return FALSE; 

ID3D11ShaderResourceView可以用来将纹理绑定到像素着色器。要渲染到渲染目标,ID3D11RenderTargetView和ID3D11DepthStencilView使用如下:

ID3D11RenderTargetView* pRTViews[1] = { pTexture0RenderTargetView.Get() };
pD3DDeviceContext->OMSetRenderTargets( 1, pRTViews, pDepthStencilView.Get() );

深度纹理

渲染目标的一个常见用途是渲染到一个深度纹理的效果,如阴影映射。Adreno GPU支持深度纹理,该功能通过GL_OES_depth_texture在OpenGL ES 2.0中公开,是OpenGL ES 3.0核心功能的一部分。然而,微软选择在Direct3D11.1特性级别9_3中不公开深度纹理。因此,实现等效效果的最简单方法是渲染为单通道32位颜色纹理(DXGI_FORMAT_R32_FLOAT),并编写一个着色器来计算深度值并将其写入颜色缓冲区。为了获得精度的最佳使用,建议将值1.0 - (z/w)写入每个像素。下面的HLSL代码块将深度值写入一个插值器,并发送给像素着色器:

vso.Position = mul(MatModelViewProj, Position);
 // Store depth for pixel shader
 // Depth is Z/W. 
 // Use 1 - z/w to get better precision
 vso.Depth = (1.0 - vso.Position.z / vso.Position.w); 

DirectX Adreno SDK中的几个例子使用了这个功能,包括DepthOfField, ShadowMap和级联阴影地图的例子。有关如何模拟深度纹理的更多细节,请参阅这些示例的源代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值