Sign in to follow this  
luasitdown

how to set rendertarget to texture map?

Recommended Posts

hi,

you do it like this:


IDirect3DTexture9* m_texture;
IDirect3DSurface9* m_surface;

HRESULT hr = pd3dDevice->CreateTexture(m_width, m_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_texture, NULL);
m_texture->GetSurfaceLevel(0, &m_surface);
pd3dDevice->SetRenderTarget(0, m_surface);





if you want to use multisampling, then it is more difficult, but I can post that one too, if you are interested.

kp

Share this post


Link to post
Share on other sites
Just one thing to add... Remember to call Release() on the surface you obtained from GetSurfaceLevel() or you get a memory leak.

-Mezz

Share this post


Link to post
Share on other sites
Quote:
Original post by kovacsp
if you want to use multisampling, then it is more difficult, but I can post that one too, if you are interested.


In DX SDK samples they suggest you cannot use texture RTs with multisampling, so they use another Z-buffer that matches their texture RT. Have you got another workaround?
~def

Share this post


Link to post
Share on other sites
I've heard that the easiest way if you want mutlisampling, just draw to the main backbuffer and copy it.

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Isn't that, like, horribly slow? Just a thought...

You mean copying backbuffer to texture? No, it's not. Only if you copy lots of large textures per frame, it starts to get slow.

Share this post


Link to post
Share on other sites
here is my code that was suggested by this post on the directx dev mailing list:

See Re: [DIRECTXDEV] How to use Multisampling with Textures? from Chuck Walbourn
September 28, 2004 at DIRECTXDEV@DISCUSS.MICROSOFT.COM


RenderTarget.hpp

#pragma once

#include "DirectXCommon.hpp"

namespace DX
{

class RenderTarget {
private:
bool m_isValid;
bool m_multisampled;
IDirect3DTexture9* m_texture;
IDirect3DSurface9* m_surface;
IDirect3DDevice9* m_pd3dDevice;
int m_width, m_height;
DDRENDERING_VIEW* m_rView;

void CopyMultisampledRenderTarget(void);

public:
RenderTarget(DDRENDERING_VIEW* p_rView);
~RenderTarget();

bool IsValid() { return(m_isValid); }
void Create(IDirect3DDevice9* p_pd3dDevice, int p_width, int p_height, bool p_multisampled, D3DMULTISAMPLE_TYPE p_multisampleType = D3DMULTISAMPLE_NONE, DWORD p_multisampleQuality = 0);

IDirect3DTexture9* GetAsTexture();
IDirect3DSurface9* GetAsSurface();

void Release();

void SaveToBmp(CString p_filename);
};

} // namespace DX





RenderTarget.cpp

#include "stdafx_DXM.h"

#include "RenderTarget.hpp"
#include "dxutil.h"

namespace DX
{

//-----------------------------------------------------------------------------
RenderTarget::RenderTarget(DDRENDERING_VIEW* p_rView)
{
m_isValid = false;
m_rView = p_rView;
m_texture = NULL;
m_surface = NULL;
}

//-----------------------------------------------------------------------------
RenderTarget::~RenderTarget()
{
if (m_isValid) {
Release();
}
}

//-----------------------------------------------------------------------------
void RenderTarget::Create(IDirect3DDevice9* p_pd3dDevice, int p_width, int p_height, bool p_multisampled, D3DMULTISAMPLE_TYPE p_multisampleType, DWORD p_multisampleQuality)
{
CCASSERT(!m_isValid); // to ensure it is not created twice

m_pd3dDevice = p_pd3dDevice;
m_multisampled = p_multisampled;
m_width = p_width;
m_height = p_height;

HRESULT hr;

// create texture
hr = m_pd3dDevice->CreateTexture(m_width, m_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_texture, NULL);
CCASSERT_MSG(hr == S_OK, "RenderTarget::CreateTexture() failed");
if (hr == D3DERR_OUTOFVIDEOMEMORY) {
UserAlertOutOfVideoMemory(m_rView);
}

if (!m_multisampled) {
// get surface
m_texture->GetSurfaceLevel(0, &m_surface);
}
else {
// create multisampled render target
hr = m_pd3dDevice->CreateRenderTarget(m_width, m_height, D3DFMT_X8R8G8B8, p_multisampleType, p_multisampleQuality, false, &m_surface, NULL);
CCASSERT_MSG(hr == S_OK, "RenderTarget::CreateRenderTarget() failed");
if (hr == D3DERR_OUTOFVIDEOMEMORY) {
UserAlertOutOfVideoMemory(m_rView);
}
}

m_isValid = true;
}

//-----------------------------------------------------------------------------
IDirect3DTexture9* RenderTarget::GetAsTexture()
{
CCASSERT(m_isValid);

if (!m_multisampled) {
// nothing
}
else {
CopyMultisampledRenderTarget();
}

return(m_texture);
}

//-----------------------------------------------------------------------------
void RenderTarget::CopyMultisampledRenderTarget(void)
{
// copy contents of multisampled surface to the non-multisampled texture
// See Re: [DIRECTXDEV] How to use Multisampling with Textures? from Chuck Walbourn
// September 28, 2004 at DIRECTXDEV@DISCUSS.MICROSOFT.COM
// http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind0409d&L=directxdev&D=1&F=&S=&P=16081

IDirect3DSurface9* surfaceOfTexture;
m_texture->GetSurfaceLevel(0, &surfaceOfTexture);

m_pd3dDevice->StretchRect(m_surface, NULL, surfaceOfTexture, NULL, D3DTEXF_LINEAR);

surfaceOfTexture->Release();
}

//-----------------------------------------------------------------------------
IDirect3DSurface9* RenderTarget::GetAsSurface()
{
CCASSERT(m_isValid);

return(m_surface);
}

//-----------------------------------------------------------------------------
void RenderTarget::Release()
{
//CCASSERT(m_isValid);

SAFE_RELEASE(m_texture);
SAFE_RELEASE(m_surface);

m_isValid = false;
}

//-----------------------------------------------------------------------------
void RenderTarget::SaveToBmp(CString p_filename)
{
if (m_multisampled) {
CopyMultisampledRenderTarget();
}

D3DXSaveTextureToFile(p_filename, D3DXIFF_BMP, m_texture, NULL);
}

} // namespace DX





Now, using this class, you can write eg.:

m_sceneAmbientRenderTarget.Create(pd3dDevice, p_desc.Width, p_desc.Height, true, d3dParams.MultiSampleType, d3dParams.MultiSampleQuality);
...
pd3dDevice->SetRenderTarget(0, m_sceneAmbientRenderTarget.GetAsSurface());




and then, when you want to use the contents of the off-screen render target as a texture, you simply write:

pd3dDevice->SetTexture(0, p_sceneAmbientRenderTarget.GetAsTexture());




Oh, almost forgot: when using this thing, I always reuse the default, multisampled depth buffer (in case multisampling is switched on, anyway it is simple). You cannot use a non-multisampled backbuffer with a multisampled rendertarget.

Please avoid the company-specific parts in the source, like CCASSERT. Sorry for that!

I don't know where, but I read thet StretchRect() is a pretty fast function. But I might be wrong. Anyway, as far as I know, this is the only way to go, and it works well for me.

Hope this helps!

kp

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this