Рендерринг в текстуру.

Содержание статьи:

Введение.
Реализация.
Создание буферов.
Пример.

Вступление.

к началу статьи
Сегодняшний туториал будет о рендерринге в текстуру. С помощью этой технологии некоторые вопросы (свечение а ля неон, отрисовка стволов в шутерах) решаются легко и просто. Суть технологии заключается в следующем: при каждом конкретном рендерринге программист имеет дело с 2 буферами – буфером кадра (хранит то что мы потом увидим на мониторе) и буфером глубины (отвечает за корректную отрисовку объектов частично или полностью перекрывающих друг друга). Фишка заключается в том, что бы перенаправить вывод геометрии в наш собственный, а не в стандартный буфер кадра (для него почти наверняка понадобится и свой буфер глубины, но это уже мелочи). После того как рендерринг будет завершен, мы вольны делать с буфером все, что нам заблагорассудится. Вот собственно и все. Можно начинать реализовывать?

Реализация.

к началу статьи
По доброй традиции начнем с класса:
DWORD				RenderTargetCleanColor = 0x000000;

class			cRenderTarget{
	LPDIRECT3DSURFACE8	OuterColorBuffer;
	LPDIRECT3DSURFACE8	OuterDepthBuffer;

	LPDIRECT3DSURFACE8	LocalColorBuffer;
	LPDIRECT3DSURFACE8	LocalDepthBuffer;
public:
	cRenderTarget( void ){
		OuterColorBuffer = NULL;
		OuterDepthBuffer = NULL;

		LocalColorBuffer = NULL;
		LocalDepthBuffer = NULL;
	}

	void		SetTextureAsRenderTarget( LPDIRECT3DDEVICE8 , LPDIRECT3DSURFACE8 );
	void		ResetRenderTarget( LPDIRECT3DDEVICE8 );
	void		GetRenderTarget( LPDIRECT3DDEVICE8 );
	void		CreateRenderTarget( LPDIRECT3DDEVICE8 , LPDIRECT3DSURFACE8 );
};
Здесь в RenderTargetCleanColor хранится цвет, которым будет очищаться внеэкранный буфер кадра, LocalColorBuffer и LocalDepthBuffer – наши буферы (буфер кадра и глубины соответственно), которыми мы будем подменять основные, OuterColorBuffer и OuterDepthBuffer – системные буферы, которые мы временно выключаем из рендерринга. Для начала нам надо научиться специальным образом создавать текстуру. Для этого дополним уже известный и не раз встречавшийся нам класс cTexture:
HRESULT		cTexture::CreateRenderTarget( LPDIRECT3DDEVICE8 Device , int w , int h ){
	return( Device->CreateTexture( w , h , 
		1 , D3DUSAGE_RENDERTARGET , 
		D3DFMT_X8R8G8B8 , D3DPOOL_DEFAULT , &Texture));
}

HRESULT	cTexture::GetSurfaceLevel( UINT Level, LPDIRECT3DSURFACE8 *ppSurfaceLevel ){
	return( Texture->GetSurfaceLevel( Level , ppSurfaceLevel ) );
}
Первая функция создает текстуру, а вторая берет указатель на LPDIRECT3DSURFACE8 (в данном случае Level должен быть равен 0 – это будет поверхность исходной текстуры). Вся особенность заключается в том, что текстура создается заданных размеров (вообще говоря, размеры текстуры – w и h - могут не являться степенями двойки) без какого-либо соотнесения с файлом с растровым изображением, а просто как область видео памяти.

Создание буферов.

к началу статьи
Теперь озаботимся созданием внеэкранных буферов. Буфер кадра создается так:
	cTexture			RTTexture;
	LPDIRECT3DSURFACE8 	TextureSurface
	RTTexture.CreateRenderTarget( D3DDevice , 256 , 256 );
	RTTexture.GetSurfaceLevel( 0 , TextureSurface );
	RenderTarget.CreateRenderTarget ( D3DDevice , TextureSurface );
Функцию CreateRenderTarget я написал следующим образом:
void	cRenderTarget::CreateRenderTarget( LPDIRECT3DDEVICE8 D3DDevice , 
					LPDIRECT3DSURFACE8 TextureSurface ){
	D3DSURFACE_DESC		Desc;
	memset( &Desc , 0 , sizeof( Desc ) );

	if( TextureSurface->GetDesc( &Desc ) == D3D_OK ){
		if( D3DDevice->CreateDepthStencilSurface( Desc.Width , 
				Desc.Height , D3DFMT_D24S8 , D3DMULTISAMPLE_NONE , 
			&LocalDepthBuffer ) != D3D_OK )
		{
			MessageBox( NULL , "Буффер глубины не был создан." , "Ошибка" , MB_OK );
			exit(0);
		}
	}

	LocalColorBuffer = TextureSurface;
}
В этой функции мы сначала узнаем параметры текстуры ( вызов GetDesc( &Desc ) ), нас интересуют только размеры, а затем создаем буфер глубины с размерами совпадающими с размерами текстуры. Собственно вся подготовка завершена, и мы можем приступать к использованию:
void	cRenderTarget::SetTextureAsRenderTarget( LPDIRECT3DDEVICE8 D3DDevice ){
	//сохраняем указатель на текущий
	//буфер цвета
	if( !OuterColorBuffer ){
		D3DDevice->GetRenderTarget( &OuterColorBuffer );
	}

	//сохраняем указатель на текущий
	//буфер глубины
	if( !OuterDepthBuffer ){
		D3DDevice->GetDepthStencilSurface( &OuterDepthBuffer );
	}

	D3DDevice->SetRenderTarget( LocalColorBuffer , LocalDepthBuffer );
	D3DDevice->Clear( 0 , NULL , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , 
		RenderTargetCleanColor , 1.0f , 0 );
}

void	cRenderTarget::ResetRenderTarget( LPDIRECT3DDEVICE8 D3DDevice ){
	if( OuterColorBuffer && OuterDepthBuffer ){
		D3DDevice->SetRenderTarget( OuterColorBuffer , OuterDepthBuffer );
		OuterColorBuffer = NULL;
		OuterDepthBuffer = NULL;
	}
	else{
		MessageBox( 0 , "Попытка установить неинициализированные поверхности." , 
			"Ошибка" , 0 );
		exit( 0 );
	}
}
В первой функции сначала сохраняем указатели на текущие буферы, а затем заменяем их нашими. Во второй функции все наоборот.

Пример.

к началу статьи
Теперь можно рассмотреть ещё один пример (инициализировать буферы мы уже научились, поэтому рассмотрим только пример рендерринга):
	RenderTarget.SetTextureAsRenderTarget( D3DDevice );

	VertexBuffer.Render( D3DDevice , FVF_D3DVERTEX );

	RenderTarget.ResetRenderTarget( D3DDevice );

	RTTexture.SetTexture( D3DDevice , 0 );

	VertexBuffer.Render( D3DDevice , FVF_D3DVERTEX );

	RTTexture.ResetTexture( D3DDevice , 0 );
В этом примере мы просто рендеррим содержимое VertexBuffer’а (там находится белый квадрат) в текстуру, а затем рендеррим его еще раз, натянув на него полученную текстуру. Вот, пожалуй, на сегодня и все. Менее тривиальные примеры использования этого класса мы рассмотрим позже, а пока до свиданья!

к началу статьи

ЗЫ: способ связи прежний dodonov_a_a@inbox.ru


Смежные вопросы:
Урок 1. Инициализация. Вершинные буфферы и камера.
Урок 2. Проигрывание медиа-файлов.
Урок 3. Автоматизация загрузки и управления аудио и видео ресурсами.
Урок 4. Текстурирование. Текстурный менеджер.
Урок 5. Шрифты в Direct3D.
Урок 6. Элементы управления.
Урок 7. Вершинные шейдеры версии 1.0.
Урок 8. Система частиц.
Исходные коды.
© 2004-2005 Savardge.ru


Hosted by uCoz