how to set rendertarget to texture map?

Started by
6 comments, last by kovacsp 18 years, 7 months ago
how to render to texture map?
Advertisement
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
------------------------------------------------------------Neo, the Matrix should be 16-byte aligned for better performance!
Just one thing to add... Remember to call Release() on the surface you obtained from GetSurfaceLevel() or you get a memory leak.

-Mezz
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
I've heard that the easiest way if you want mutlisampling, just draw to the main backbuffer and copy it.
Isn't that, like, horribly slow? Just a thought...
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.
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
------------------------------------------------------------Neo, the Matrix should be 16-byte aligned for better performance!

This topic is closed to new replies.

Advertisement