我正在创建两个渲染目标,两者都必须共享后缓冲区的深度缓冲区,因此我将它们设置为具有相同的多采样参数非常重要,但是pDevice-> CreateTexture(..)不提供任何参数用于设置多采样类型。所以我使用pDevice-> CreateRenderTarget(...)创建了两个渲染目标曲面,给出了与深度缓冲区相同的值,现在深度缓冲区与我的渲染目标一起工作,但是我无法在屏幕上正确渲染它们因为alpha混合不适用于 - > StretchRect(或者我被告知,当我尝试时它不起作用)。
所以这个问题的标题基本上都是我的问题,我该怎么做: - 将表面转换为纹理或 - 使用某些多重采样参数创建纹理或 - 使用alpha图层正确渲染表面
答案 0 :(得分:1)
StretchRect的文档具体说明了如何执行此操作:
使用StretchRect下采样a 多重样本Rendertarget
您可以使用StretchRect进行复制 一个rendertarget到另一个。如果 source rendertarget是多重采样的, 这会导致下采样 source rendertarget。比如你 可以:
- 创建多重采样的rendertarget。
- 创建第二个rendertarget 大小相同,不是多重采样。
- 复制(使用StretchRect 多样本rendertarget到第二个 渲染目标。
注意使用 涉及使用的额外表面 StretchRect下采样a 将产生多重采样Rendertarget 在一次表演中。
答案 1 :(得分:1)
对旧问题的新回应,但我遇到了这个并认为我会提供一个答案,以防其他人碰到这个问题。这是我的包装器及其功能的精简版本的解决方案。
我有一个游戏,其中渲染器有几个图层,其中一个是几何图层。渲染时,它遍历所有图层,调用其Draw函数。每个图层都有自己的RenderTarget包装器实例。当图层绘制时,它“激活”其渲染目标,将缓冲区清除为alpha,绘制场景,然后“停用”其渲染目标。在所有图层都绘制到渲染目标后,所有这些渲染目标都会合并到后台缓冲区上以生成最终图像。
GeometryLayer ::绘制
*激活此图层使用的渲染目标
*设置所需的渲染状态
*清除缓冲区
*绘制几何体
*取消激活此图层使用的渲染目标
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 ::初始化
*创建纹理
*从纹理中获取一个曲面(添加到曲面的引用计数)
*如果是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 ::激活
*存储当前渲染目标(添加到该曲面的引用计数)
*如果不是MSAA,则将surface设置为新的渲染目标
*如果MSAA将msaa surface设置为新的渲染目标,则启用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 ::停用
*如果是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通道的格式,这个纹理可以与其他纹理混合,就像我正在使用多个图层的渲染目标一样。