Статьи/Цикл уроков по DirectX 9.0/Урок 03: Использование текстур
Урок 03: Использование текстур


Мы уже научились инициализировать Direct3D и выводить простые полиональные объекты. Но они как-то странно выглядят. Для придания простым малополигональным объектам 3D сцен в Direct3D можно наложить на них текстуры - простые двухмерные картинки с каким либо рисунком, заменяющим натуральный рельеф.

Итак для отображения текстур нам всего лишь необходимо в каждой вершине модели указать текстурные координаты. В соответствии с ними 2D картинка будет накладываться на поигон. Так как мы отображаем кубик - восемью вершинами нам необойтись, поэтому в этом уроке мы откажемся от индексного буфера, и будем пользоваться только вершинным... Начнем.
Каркас возьмем из первого урока. Теперь будем просто добавлять в него недостающий текст.

В начале объявим вершинный буфер и указатель на нашу будущую текстуру:

LPDIRECT3DVERTEXBUFFER9 MyVertexBuffer;			// Вертекс буфер для отрисовки кубика
LPDIRECT3DTEXTURE9	MyTexture;			// Текстура для нашего кубика

Структура наших вершин обновилась. Теперь вершины содержат еще и две текстурные координаты:

struct MyVertex
{
	float	x,y,z;
	DWORD	color;
	float	tx,ty;	// Координаты текстуры
};

Формат вершин тоже не остался без изменений:

DWORD MyVertex_FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;

Функции инициализации AllInit обновилась: сначала инициализируем Direct3D, потом создаем буфер вершин, заполняем массив вершин, заполненяем вершинный буфер, и наконец самое главное загружаем нашу текстуру из файла! Выглядит она теперь вот так:

bool AllInit()
{
	if(!InitD3D(Width, Height, fullscreen))
		return false;

	if( FAILED( g_pd3dDevice->CreateVertexBuffer(
		36*sizeof(MyVertex),	// Размер буфера (в нашем случае 36 вершин
					// каждая размером в структуру MyVertex)
		D3DUSAGE_WRITEONLY,	// Используем буфер только для чтения (быстрее)
		MyVertex_FVF,		// Формат наших вершин
		D3DPOOL_MANAGED,	// DirectX сам управляет пересозданием буфера
		&MyVertexBuffer,	// Наш указатель на буфер
		NULL			// Оставим NULL
		) ) )
		return false;		// Если произошла ошибка сообщить об этом

	// Вершины для кубика
	MyVertex v[] =
	{
		{ -1.0f, -1.0f,  1.0f, D3DCOLOR_XRGB( 255,   0,   0), 0.0f, 0.0f,},
		{  1.0f, -1.0f,  1.0f, D3DCOLOR_XRGB( 255,   0,   0), 1.0f, 0.0f,},
		{  1.0f,  1.0f,  1.0f, D3DCOLOR_XRGB( 255,   0,   0), 1.0f, 1.0f,}, 
		{ -1.0f, -1.0f,  1.0f, D3DCOLOR_XRGB( 255,   0,   0), 0.0f, 0.0f,},
		{  1.0f,  1.0f,  1.0f, D3DCOLOR_XRGB( 255,   0,   0), 1.0f, 1.0f,}, 
		{ -1.0f,  1.0f,  1.0f, D3DCOLOR_XRGB( 255,   0,   0), 0.0f, 1.0f,}, 

		{ -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(   0, 255,   0), 1.0f, 0.0f,}, 
		{ -1.0f,  1.0f, -1.0f, D3DCOLOR_XRGB(   0, 255,   0), 1.0f, 1.0f,},
		{  1.0f,  1.0f, -1.0f, D3DCOLOR_XRGB(   0, 255,   0), 0.0f, 1.0f,}, 
		{ -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(   0, 255,   0), 1.0f, 0.0f,},
		{  1.0f,  1.0f, -1.0f, D3DCOLOR_XRGB(   0, 255,   0), 0.0f, 1.0f,}, 
		{  1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(   0, 255,   0), 0.0f, 0.0f,},

		{ -1.0f,  1.0f, -1.0f, D3DCOLOR_XRGB(   0,   0, 255), 0.0f, 1.0f,}, 
		{ -1.0f,  1.0f,  1.0f, D3DCOLOR_XRGB(   0,   0, 255), 0.0f, 0.0f,},
		{  1.0f,  1.0f,  1.0f, D3DCOLOR_XRGB(   0,   0, 255), 1.0f, 0.0f,}, 
		{ -1.0f,  1.0f, -1.0f, D3DCOLOR_XRGB(   0,   0, 255), 0.0f, 1.0f,}, 
		{  1.0f,  1.0f,  1.0f, D3DCOLOR_XRGB(   0,   0, 255), 1.0f, 0.0f,}, 
		{  1.0f,  1.0f, -1.0f, D3DCOLOR_XRGB(   0,   0, 255), 1.0f, 1.0f,},
		
		{ -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB( 255, 255,   0), 1.0f, 1.0f,}, 
		{  1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB( 255, 255,   0), 0.0f, 1.0f,},
		{  1.0f, -1.0f,  1.0f, D3DCOLOR_XRGB( 255, 255,   0), 0.0f, 0.0f,}, 
		{ -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB( 255, 255,   0), 1.0f, 1.0f,}, 
		{  1.0f, -1.0f,  1.0f, D3DCOLOR_XRGB( 255, 255,   0), 0.0f, 0.0f,}, 
		{ -1.0f, -1.0f,  1.0f, D3DCOLOR_XRGB( 255, 255,   0), 1.0f, 0.0f,},
		
		{  1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB( 255,   0, 255), 1.0f, 0.0f,}, 
		{  1.0f,  1.0f, -1.0f, D3DCOLOR_XRGB( 255,   0, 255), 1.0f, 1.0f,},
		{  1.0f,  1.0f,  1.0f, D3DCOLOR_XRGB( 255,   0, 255), 0.0f, 1.0f,}, 
		{  1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB( 255,   0, 255), 1.0f, 0.0f,}, 
		{  1.0f,  1.0f,  1.0f, D3DCOLOR_XRGB( 255,   0, 255), 0.0f, 1.0f,}, 
		{  1.0f, -1.0f,  1.0f, D3DCOLOR_XRGB( 255,   0, 255), 0.0f, 0.0f,},
		
		{ -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB( 255, 255, 255), 0.0f, 0.0f,}, 
		{ -1.0f, -1.0f,  1.0f, D3DCOLOR_XRGB( 255, 255, 255), 1.0f, 0.0f,},
		{ -1.0f,  1.0f,  1.0f, D3DCOLOR_XRGB( 255, 255, 255), 1.0f, 1.0f,}, 
		{ -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB( 255, 255, 255), 0.0f, 0.0f,}, 
		{ -1.0f,  1.0f,  1.0f, D3DCOLOR_XRGB( 255, 255, 255), 1.0f, 1.0f,}, 
		{ -1.0f,  1.0f, -1.0f, D3DCOLOR_XRGB( 255, 255, 255), 0.0f, 1.0f,}
	};

	void * pBuf;
	// заполненяем вершинный буфер
	MyVertexBuffer->Lock( 0, 36 * sizeof(MyVertex), &pBuf, 0 );
	memcpy( pBuf, v, 36 * sizeof(MyVertex));
	MyVertexBuffer->Unlock();

	// Загружаем текстуру из файла
	D3DXCreateTextureFromFile(g_pd3dDevice, "Texture.bmp", &MyTexture);

	ReInit();
	return true;
}

Теперь переходим к самому сладкому - отрисовке сцены. И вставим в секцию
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
}

следующих код:

		// переменная для плавного переливания фона (для красоты)...
		float time=GetTickCount()/2048.0f;

		// Очищаем задний буфер и буфер глубины
		g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
			D3DCOLOR_XRGB(
			int((cos(time*2.0f)+1.0f)/2.0f*255),
			int((cos(time     )+1.0f)/2.0f*255),
			int((sin(time*2.0f)+1.0f)/2.0f*255)), 1.0f, 0L);

		//--------------------------//
		// Здесь мы будем рисовать! //
		//--------------------------//

		D3DXMATRIX matWorld;
		D3DXMatrixRotationYawPitchRoll( &matWorld, 
		GetTickCount()/1024.0f, GetTickCount()/2048.0f, GetTickCount()/2048.0f );

		g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);


		D3DXMATRIX matView;
		D3DXMatrixLookAtLH(&matView,
			&D3DXVECTOR3(4.0f, 4.0f, 4.0f),		// Точка из которой мы смотрим
								// Место положения камеры
			&D3DXVECTOR3(0.0f, 0.0f, 0.0f),		// Точка в которую смотрим
			&D3DXVECTOR3(0.0f, 1.0f, 0.0f));	// Где верх?
		g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);

		// Устанавливаем вершинный буфер
		g_pd3dDevice->SetStreamSource( 0, MyVertexBuffer, 0, sizeof(MyVertex) );
		// устанавливаем формат вершин
		g_pd3dDevice->SetFVF( MyVertex_FVF );

		// Если текстура нормально загрузилась
		if( MyTexture != NULL )
			g_pd3dDevice->SetTexture(0, MyTexture); // Ставим текстуру

		// Устанавливаем фильтрацию текстур
		// Поэкспериментируйте - увидите разницу:
		//
		// D3DTEXF_NONE			- фильтрация не испоьзуется
		// D3DTEXF_POINT		- точечная фильтрация
		// D3DTEXF_LINEAR		- линейная фильтрация
		// D3DTEXF_ANISOTROPIC	- анизотропная фильтрация
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

		// Производим отрисовку
		g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 12);


		g_pd3dDevice->EndScene();			// Закончили рисовать
		g_pd3dDevice->Present( NULL, NULL, NULL, NULL );// Отображаем задний буфер

Осталось только в AllShutdown() освободить память из-под всех созданных объектов:

void AllShutdown()
{
	Cleanup();

	SAFE_RELEASE(MyTexture);		// Освобождаем память из-под текстуры
	SAFE_RELEASE(MyVertexBuffer);
	SAFE_RELEASE(g_pd3dDevice);
	SAFE_RELEASE(g_pD3D);
}

Теперь вы умеете загружать текстуры в Direct3D, и ваши программы будут выглядеть намного эффектнее.
Исходник берите ЗДЕСЬ! (~173Kb)
ДоZZZвидания!

Автор: L1f 





Рейтинг@Mail.ru