I am attempting to do a Render to Texture such that the surface rendered to is transparent.
This is so I can later use that texture to overlay a 2D scene with 3D objects (obviously, if not transparent, can't see what's underneath).
The following works properly for Render to Texture, however, the image saved is fully opaque (I assume this to be that RenderTargets don't support Transparency) and since it's saved fully opaque, I have to imagine that's how it would appear on geometry rendered at a later time.
HRESULT Camera::RenderToTexture(Node* pScene)
{
Wnd* pDisplay = pScene->GetDisplay();
if (!pDisplay->m_pDevice)
return E__NODEVICE;
IDirect3DDevice9* pDevice = pDisplay->m_pDevice;
HRESULT hr = S_OK;
// original
IDirect3DSurface9* renderTarget = NULL;
IDirect3DSurface9* depthTarget = NULL;
// new
IDirect3DSurface9* renderTarget_ = NULL;
IDirect3DSurface9* depthTarget_ = NULL;
// render target
hr = pDevice->GetRenderTarget(0, &renderTarget); // currently set render target for restoration
if (D3D_OK == hr)
{
D3DSURFACE_DESC desc; renderTarget->GetDesc(&desc);
// m_fCamWidth = 1080; m_fCamHeight = 1920;
hr = pDevice->CreateRenderTarget((UINT)m_fCamWidth, (UINT)m_fCamHeight, desc.Format,
desc.MultiSampleType, desc.MultiSampleQuality,
false, &renderTarget_, NULL);
THROW_IF_FAILED(hr);
}
// matching depth target
hr = pDevice->GetDepthStencilSurface(&depthTarget); // currently set depth target for restoration
if (D3D_OK == hr)
{
D3DSURFACE_DESC desc; depthTarget->GetDesc(&desc);
// m_fCamWidth = 1080; m_fCamHeight = 1920;
hr = pDevice->CreateDepthStencilSurface((UINT)m_fCamWidth, (UINT)m_fCamHeight, desc.Format,
desc.MultiSampleType, desc.MultiSampleQuality,
false, &depthTarget_, NULL);
THROW_IF_FAILED(hr);
}
if (renderTarget_) pDevice->SetRenderTarget(0, renderTarget_);
if (depthTarget_) pDevice->SetDepthStencilSurface(depthTarget_);
// hierarchy flattening
THROW_IF_FAILED(pScene->UpdateTransform());
THROW_IF_FAILED(pDevice->SetTransform(D3DTS_PROJECTION, &m_matProjection));
THROW_IF_FAILED(pDevice->SetTransform(D3DTS_VIEW, &m_matView));
THROW_IF_FAILED(pDevice->BeginScene());
THROW_IF_FAILED(pDevice->Clear(NULL, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_ARGB(0, 128, 128, 128), 1.0f, 0));
// hierarchy rendering
pScene->Render();
pDevice->SetRenderTarget(0, renderTarget);
pDevice->SetDepthStencilSurface(depthTarget);
LPDIRECT3DTEXTURE9 textureMap; CreateTexture(textureMap, pDisplay);
LPDIRECT3DSURFACE9 l_Surface; textureMap->GetSurfaceLevel(0, &l_Surface);
pDevice->StretchRect(renderTarget_, NULL, l_Surface, NULL, D3DTEXF_NONE);
D3DXSaveTextureToFile("D:\\output.png", D3DXIMAGE_FILEFORMAT::D3DXIFF_PNG, textureMap, NULL);
SAFE_RELEASE(renderTarget_);
SAFE_RELEASE(depthTarget_);
SAFE_RELEASE(renderTarget);
SAFE_RELEASE(depthTarget);
THROW_IF_FAILED(pDevice->EndScene());
return hr;
}
CreateTexture function:
HRESULT Camera::CreateTexture(LPDIRECT3DTEXTURE9& _pTextureMap, Wnd* _pDisplay)
{
IDirect3DDevice9* pDevice = _pDisplay->m_pDevice;
HRESULT hr = S_OK;
//m_fCamWidth = 1080; m_fCamHeight = 1920;
hr = D3DXCreateTexture(pDevice,
(UINT)m_fCamWidth, (UINT)m_fCamHeight,
D3DX_DEFAULT,
D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT,
&_pTextureMap);
//Note: If you want the alpha channel then use D3DFMT_A8R8G8B8 format.
return hr;
}
Current Render States:
D3DRS_AMBIENT, RGB(255, 255, 255)
0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2
0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU
1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2
1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU
Unfortunately, I have to do this without the assist of shaders.
While technically I could save the image every frame and load it with a color key, this isn't a grand solution to me.
Current Output (from source code)

Corrected Output (edited via Paint.net)

edit: Added the following, to no avail:
pDevice->SetRenderState(D3DRENDERSTATETYPE::D3DRS_ALPHABLENDENABLE, TRUE);
pDevice->SetRenderState(D3DRENDERSTATETYPE::D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pDevice->SetRenderState(D3DRENDERSTATETYPE::D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
I've verified the Formats of my RenderTarget & Texture; both are D3DFMT_A8R8G8B8
edit 2:
Realizing I had a couple redundancies, I reduced some of what I was doing to make it a little less complex. However, I seem to be unable to clear my RenderTarget to transparent.
HRESULT Camera::RenderToTexture(Node* pScene)
{
Wnd* pDisplay = pScene->GetDisplay();
if (!pDisplay->m_pDevice)
return E__NODEVICE;
IDirect3DDevice9* pDevice = pDisplay->m_pDevice;
HRESULT hr = S_OK;
// original
IDirect3DSurface9* renderTarget = NULL;
IDirect3DSurface9* depthTarget = NULL;
// new
LPDIRECT3DTEXTURE9 textureMap = NULL;
IDirect3DSurface9* depthTarget_ = NULL;
// render target
hr = pDevice->GetRenderTarget(0, &renderTarget); // currently set render target for restoration
if (D3D_OK == hr)
{
CreateTexture(textureMap, pDisplay);
LPDIRECT3DSURFACE9 l_Surface; textureMap->GetSurfaceLevel(0, &l_Surface);
THROW_IF_FAILED(hr);
pDevice->SetRenderTarget(0, l_Surface);
}
// matching depth target
hr = pDevice->GetDepthStencilSurface(&depthTarget); // currently set depth target for restoration
if (D3D_OK == hr)
{
D3DSURFACE_DESC desc; depthTarget->GetDesc(&desc);
hr = pDevice->CreateDepthStencilSurface((UINT)m_fCamWidth, (UINT)m_fCamHeight, desc.Format,
desc.MultiSampleType, desc.MultiSampleQuality,
false, &depthTarget_, NULL);
THROW_IF_FAILED(hr);
pDevice->SetDepthStencilSurface(depthTarget_);
}
THROW_IF_FAILED(pScene->UpdateTransform());
THROW_IF_FAILED(pDevice->SetTransform(D3DTS_PROJECTION, &m_matProjection));
THROW_IF_FAILED(pDevice->SetTransform(D3DTS_VIEW, &m_matView));
THROW_IF_FAILED(pDevice->BeginScene());
THROW_IF_FAILED(pDevice->Clear(NULL, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_RGBA(128, 12, 1, 0), 1.0f, 0));
pDevice->SetRenderState(D3DRENDERSTATETYPE::D3DRS_ALPHABLENDENABLE, TRUE);
pDevice->SetRenderState(D3DRENDERSTATETYPE::D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pDevice->SetRenderState(D3DRENDERSTATETYPE::D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
pScene->Render();
pDevice->SetRenderTarget(0, renderTarget);
pDevice->SetDepthStencilSurface(depthTarget);
D3DXSaveTextureToFile("D:\\output.png", D3DXIMAGE_FILEFORMAT::D3DXIFF_PNG, textureMap, NULL);
SAFE_RELEASE(depthTarget_);
SAFE_RELEASE(renderTarget);
SAFE_RELEASE(depthTarget);
THROW_IF_FAILED(pDevice->EndScene());
return hr;
}