Page 1 of 1

Floating Point Render Target Texture Support [DX9]

Posted: Fri Dec 28, 2007 9:37 pm
by Nadro
Hi. I done floating point render target support for Irrlicht [Now for DirectX9 only, but I'm working on it for OpenGL]

I add 6 new color format:

Code: Select all

ECF_R16F
ECF_G16R16F
ECF_A16B16G16R16F
ECF_R32F
ECF_G32R32F
ECF_A32B32G32R32F
You have to update this Irrlicht parts for usage fp textures:

Code: Select all

		             *** Irrlicht Include ***

---------------------------------------- IImage.h ----------------------------------------
enum ECOLOR_FORMAT
{
	//! 16 bit color format used by the software driver, and thus preferred
	//! by all other irrlicht engine video drivers. There are 5 bits for every
	//! color component, and a single bit is left for alpha information.
	ECF_A1R5G5B5 = 0,

	//! Standard 16 bit color format.
	ECF_R5G6B5,

	//! 24 bit color, no alpha channel, but 8 bit for red, green and blue.
	ECF_R8G8B8,

	//! Default 32 bit color format. 8 bits are used for every component:
	//! red, green, blue and alpha.
	ECF_A8R8G8B8,

	// ** Floating Point ***

	//! 16 bit float format using. 16 bits for red:
	ECF_R16F,

	//! 32 bit float format using. 16 bits for red and 16 bits for green:
	ECF_G16R16F,

	//! 64 bit float format. 16 bits are used for every component:
	//! red, green, blue and alpha.
	ECF_A16B16G16R16F,

	//! 32 bit float format using. 32 bits for red:
	ECF_R32F,

	//! 64 bit float format using. 32 bits for red and 32 bits for green:
	ECF_G32R32F,

	//! 128 bit float format. 32 bits are used for every component:
	//! red, green, blue and alpha.
	ECF_A32B32G32R32F,

	//! Unknown color format:
	ECF_UNKNOWN,
};
------------------------------------------------------------------------------------------
********************************************************************

------------------------------------- IVideoDriver.h -------------------------------------
virtual ITexture* createRenderTargetTexture(const core::dimension2d<s32>& size, const c8* name = 0, ECOLOR_FORMAT format = ECF_UNKNOWN) = 0;
------------------------------------------------------------------------------------------
********************************************************************

		             *** Irrlicht Source ***

------------------------------------- CNullDriver.h -------------------------------------
virtual ITexture* createRenderTargetTexture(const core::dimension2d<s32>& size, const c8* name = 0, ECOLOR_FORMAT format = ECF_UNKNOWN);
------------------------------------------------------------------------------------------
********************************************************************

------------------------------------ CNullDriver.cpp ------------------------------------
ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d<s32>& size, const c8* name, ECOLOR_FORMAT format)
{
	return 0;
}
------------------------------------------------------------------------------------------
********************************************************************

------------------------------------ CD3D9Driver.h ------------------------------------
virtual ITexture* createRenderTargetTexture(const core::dimension2d<s32>& size, const c8* name = 0, ECOLOR_FORMAT format = ECF_UNKNOWN);
------------------------------------------------------------------------------------------
********************************************************************

----------------------------------- CD3D9Driver.cpp -----------------------------------
ITexture* CD3D9Driver::createRenderTargetTexture(const core::dimension2d<s32>& size, const c8* name, ECOLOR_FORMAT format)
{
	return new CD3D9Texture(this, size, name, format);
}
------------------------------------------------------------------------------------------
********************************************************************

------------------------------------ CD3D9Texture.h -----------------------------------
//! rendertarget constructor
CD3D9Texture(CD3D9Driver* driver, core::dimension2d<s32> size, const char* name, ECOLOR_FORMAT format = ECF_UNKNOWN);
------------------------------------------------------------------------------------------
void createRenderTarget(ECOLOR_FORMAT format);
------------------------------------------------------------------------------------------
********************************************************************

----------------------------------- CD3D9Texture.cpp ----------------------------------
//! rendertarget constructor
CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, core::dimension2d<s32> size, const char* name, ECOLOR_FORMAT format)
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver),
	TextureSize(size), ImageSize(size), Pitch(0),
	HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true)
{
	#ifdef _DEBUG
	setDebugName("CD3D9Texture");
	#endif

	Device=driver->getExposedVideoData().D3D9.D3DDev9;
	if (Device)
		Device->AddRef();

	createRenderTarget( format );
}
------------------------------------------------------------------------------------------
void CD3D9Texture::createRenderTarget(video::ECOLOR_FORMAT format)
{
	TextureSize.Width = getTextureSizeFromImageSize(TextureSize.Width);
	TextureSize.Height = getTextureSizeFromImageSize(TextureSize.Height);

	D3DFORMAT d3DFormat = D3DFMT_A8R8G8B8;

	if( format == ECF_UNKNOWN )
	{
		// get backbuffer format to create the render target in the
		// same format
		IDirect3DSurface9* bb;	

		if (!FAILED(Device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &bb)))
		{
			D3DSURFACE_DESC desc;
			bb->GetDesc(&desc);
			d3DFormat = desc.Format;

			if (d3DFormat == D3DFMT_X8R8G8B8)
				d3DFormat = D3DFMT_A8R8G8B8;

			bb->Release();
		}
		else
		{
			os::Printer::log("Could not create RenderTarget texture: could not get BackBuffer.",
				ELL_WARNING);
			return;
		}
	}
	else
	{
		d3DFormat = getD3DFormatFromColorFormat( format );
	}

	if( d3DFormat != D3DFMT_UNKNOWN )
	{
		// create texture
		HRESULT hr;

		hr = Device->CreateTexture(
			TextureSize.Width,
			TextureSize.Height,
			1, // mip map level count, we don't want mipmaps here
			D3DUSAGE_RENDERTARGET,
			d3DFormat,
			D3DPOOL_DEFAULT,
			&Texture,
			NULL);

		// get irrlicht format from D3D format
		ColorFormat = getColorFormatFromD3DFormat(d3DFormat);

		if (FAILED(hr))
		os::Printer::log("Could not create render target texture");
	}
	else
	{
		os::Printer::log( "Can not create render target of format D3DFMT_UNKNOWN" );
	}
}
------------------------------------------------------------------------------------------
D3DFORMAT CD3D9Texture::getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const
{
	switch(format)
	{
		case ECF_A1R5G5B5:
			return D3DFMT_A1R5G5B5;
		case ECF_R5G6B5:
			return D3DFMT_R5G6B5;
		case ECF_R8G8B8:
			return D3DFMT_R8G8B8;
		case ECF_A8R8G8B8:
			return D3DFMT_A8R8G8B8;

		// ** Floating Point ***

		case ECF_R16F:
			return D3DFMT_R16F;
		case ECF_G16R16F:
			return D3DFMT_G16R16F;
		case ECF_A16B16G16R16F:
			return D3DFMT_A16B16G16R16F;
		case ECF_R32F:
			return D3DFMT_R32F;
		case ECF_G32R32F:
			return D3DFMT_G32R32F;
		case ECF_A32B32G32R32F:
			return D3DFMT_A32B32G32R32F;
	}
	return D3DFMT_UNKNOWN;
}
------------------------------------------------------------------------------------------
********************************************************************
You have to update createRenderTargetTexture function for all Your driver eg. Software Driver, OpenGL.

Simple usage:

Code: Select all

ITexture* rt = driver->createRenderTargetTexture(core::dimension2d<s32>(256,256),0,video::ECF_A16B16G16R16F);
I tested it on shadow mapping example and works fine:) This is code for Irrlicht 1.4 but it's easy to implementation for SVN revision. Maybe Irrlicht Team can merge it with Irrlicht core on SVN, when I add OpenGL support? Floating point is very useful for creating shaders eg. HDR, Shadow Mapping etc.

Posted: Sat Dec 29, 2007 2:46 am
by BlindSide
Cool :D

Before I was using this snippet to store 32bit floating point info in a texture:

Code: Select all

/// Packing a [0-1] float value into a 4D vector where each component will be a 8-bits integer
vec4 packFloatToVec4i(const float value)
{
	const vec4 bitSh = vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
	const vec4 bitMsk = vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
	vec4 res = fract(value * bitSh);
	res -= res.xxyz * bitMsk;
	return res;
}

float unpackFloatFromVec4i(const vec4 value)
{
	const vec4 bitSh = vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0);
	return(dot(value, bitSh));
}
Anyway, thanks :D

Posted: Sun Dec 30, 2007 12:08 pm
by hybrid
The problem (and why it was not yet integrated into Irrlicht) is that no one will stop you from creating IImages with these values. But no method in Irrlicht will cope with it. Moreover, you cannot lock textures of this format for access (at most downsampled versions might be available). Due to the current way SColor, IImage, and ITexture are implemented, there is no easy way to overcome this limitation.

Posted: Sun Dec 30, 2007 12:38 pm
by Nadro
Floating point textures is usage for Shaders [HDR, Deferred Shading, Shadow Mapping etc...], so You don't need use lock texture, convert it to another etc. Users need standard floating point operation - write Render to Height Precision Texture, so this tip solved this problem in 100% In future We can odd full support operations on FP Texture Format eg. lock but now We need add simple support for this texture in Irrlicht :)

Posted: Tue Jan 01, 2008 8:52 pm
by Nadro
If You need integrated MRTs with Floating Point Textures and support this in OpenGL and DirectX9 You should go to this topic:
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=25496