2

我正在创建两个渲染目标,它们都必须共享后台缓冲区的深度缓冲区,因此将它们设置为具有相同的多重采样参数很重要,但是 pDevice->CreateTexture(..) 没有提供任何用于设置多重采样的参数采样类型。所以我使用 pDevice->CreateRenderTarget(...) 创建了两个渲染目标表面,给出与深度缓冲区相同的值,现在深度缓冲区与我的渲染目标一起工作,但是我无法在屏幕上正确渲染它们,因为alpha 混合不适用于 ->StretchRect (或者我被告知,并且在我尝试时它不起作用)。

所以这个问题的标题基本上是我的问题,我如何: - 将表面转换为纹理或 - 使用某些多重采样参数创建纹理或 - 使用 alpha 层正确渲染表面

4

2 回答 2

2

The documentation for StretchRect specifically explains how to do this:

Using StretchRect to downsample a Multisample Rendertarget

You can use StretchRect to copy from one rendertarget to another. If the source rendertarget is multisampled, this results in downsampling the source rendertarget. For instance you could:

  • Create a multisampled rendertarget.
  • Create a second rendertarget of the same size, that is not multisampled.
  • Copy (using StretchRect the multisample rendertarget to the second rendertarget.

Note that use of the extra surface involved in using StretchRect to downsample a Multisample Rendertarget will result in a performance hit.

于 2011-03-30T21:43:05.767 回答
2

对一个老问题的新回应,但我遇到了这个问题,并认为我会提供一个答案,以防其他人在遇到这个问题时遇到它。这是我的包装器和函数的精简版本的解决方案。

我有一个游戏,其中渲染器有几个层,其中一个是几何层。渲染时,它遍历所有层,调用它们的 Draw 函数。每个层都有自己的 RenderTarget 包装器实例。当图层绘制时,它“激活”其渲染目标,将缓冲区清除为 alpha,绘制场景,然后“停用”其渲染目标。在所有图层都绘制到它们的渲染目标之后,所有这些渲染目标然后组合到后缓冲区以生成最终图像。

GeometryLayer::Draw
* 激活此层使用的渲染目标
* 设置所需
的渲染状态 * 清除缓冲区
* 绘制几何体
* 停用此层使用的渲染目标

void GeometryLayer::Draw( const math::mat4& viewProjection )
{
    m_pRenderTarget->Activate();

    pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
    pDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
    pDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);

    pDevice->Clear(0,0,D3DCLEAR_TARGET,m_clearColor,1.0,0);
    pDevice->BeginScene();
    pDevice->Clear(0,0,D3DCLEAR_ZBUFFER,0,1.0,0);

    for(auto it = m->visibleGeometry.begin(); it != m->visibleGeometry.end(); ++it)
        it->second->Draw(viewProjection);

    pDevice->EndScene();

    m_pRenderTarget->Deactivate();
}

我的 RenderTarget 包装器包含一个 IDirect3DTexture9* (m_pTexture),它与 ​​D3DXCreateTexture 一起使用以生成要绘制到的纹理。它还包含一个由纹理给出的 IDirect3DSurface9* (m_pSurface)。它还包含另一个 IDirect3DSurface9* (m_pMSAASurface)。

在我的 RenderTarget 的初始化中,有一个启用多重采样的选项。如果关闭此选项,则 m_pMSAASurface 将初始化为 nullptr。如果启用此选项,则会使用 IDirect3DDevice9::CreateRenderTarget 函数为您创建 m_pMSAASurface,并将我当前的多重采样设置指定为第 4 和第 5 个参数。

RenderTarget::Init
* 创建纹理
* 从纹理中获取表面(添加到表面的引用计数)
* 如果是 MSAA,则创建启用 msaa 的表面

void    RenderTarget::Init(const int width,const int height,const bool enableMSAA)
{
    m_bEnableMSAA = enableMSAA;
    D3DXCreateTexture(pDevice,
        width,
        height,
        1,
        D3DUSAGE_RENDERTARGET,
        D3DFMT_A8R8G8B8,
        D3DPOOL_DEFAULT,
        &m_pTexture;
    );
    m_pTexture->GetSurfaceLevel(0,&m_pSurface);

    if(enableMSAA)
    {
        Renderer::GetInstance()->GetDevice()->CreateRenderTarget(
            width,
            height,
            D3DFMT_A8R8G8B8,
            d3dpp.MultiSampleType,
            d3dpp.MultiSampleQuality,
            false,
            &m_pMSAAsurface,
            NULL
        );
    }
}

如果此 MSAA 设置关闭,则 RenderTarget::Activate 将 m_pSurface 设置为渲染目标。如果启用此 MSAA 设置,则 RenderTarget::Activate 将 m_pMSAASurface 设置为渲染目标并启用多重采样渲染状态。

RenderTarget::Activate
* 存储当前渲染目标(添加到该表面的引用计数)
* 如果不是 MSAA,则将表面设置为新的渲染目标
* 如果 MSAA,将 msaa 表面设置为新的渲染目标,启用 msaa 渲染状态

void    RenderTarget::Activate()
{
    pDevice->GetRenderTarget(0,&m_pOldSurface);

    if(!m_bEnableMSAA)
    {
        pDevice->SetRenderTarget(0,m_pSurface);
    }
    else
    {
        pDevice->SetRenderTarget(0,m_pMSAAsurface);
        pDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS,true);
    }
}

如果此 MSAA 设置关闭,则 RenderTarget::Deactivate 只会恢复原始渲染目标。如果启用此 MSAA 设置,RenderTarget::Deactivate 也会恢复原始渲染目标,但也会将 m_pMSAASurface 复制到 m_pSurface。

RenderTarget::Deactivate
* 如果是 MSAA,则禁用 MSAA 渲染状态
* 恢复前一个渲染目标
* 丢弃前一个渲染目标上的引用计数

void    RenderTarget::Deactivate()
{
    if(m_bEnableMSAA)
    {
        pDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS,false);
        pDevice->StretchRect(m_pMSAAsurface,NULL,m_pSurface,NULL,D3DTEXF_NONE);
    }
    pDevice->SetRenderTarget(0,m_pOldSurface);

    m_pOldSurface->Release();
    m->pOldSurface = nullptr;
}

当渲染器稍后向几何层询问其 RenderTarget 纹理以便将其与其他层组合时,该纹理具有从 m_pMSAASurface 复制的图像。假设您使用的是促进 Alpha 通道的格式,则此纹理可以与其他纹理混合,就像我正在处理多个图层的渲染目标一样。

于 2013-12-13T06:30:11.177 回答