Шаг 18 - Деревянная стена или плоское покрытие текстурой

Настало время нам оградиться стеной :)

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

#define D3DFVF_CUSTOMVERTEX ( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)

struct CUSTOMVERTEX { float x, y, z, nx, ny, nz, tu, tv; };

Установим новые вершины:

CUSTOMVERTEX g_Vertices[] =
{
	{ -100.0f,   0.0f,  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,},
	{ -100.0f, 180.0f,  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,},
	{  100.0f, 180.0f,  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,},

	{ -100.0f,   0.0f, 0.0f, 0.0f, 0.0f,  0.0f, 0.0f, 0.0f,},
	{  100.0f, 180.0f, 0.0f, 0.0f, 0.0f,  0.0f, 0.0f, 0.0f,},
	{  100.0f,   0.0f, 0.0f, 0.0f, 0.0f,  0.0f, 0.0f, 0.0f,},
};

Перейдем в функцию Transform3D и изменим параметры камеры или глаза наблюдателя, кому как удобней, повыше и заодно поставим сцену в исходное положение.

D3DXMatrixRotationY (&matWorld, 0.0f);

D3DXMatrixLookAtLH (&matView, &D3DXVECTOR3 (0.0f, 500.0f, -500.0f),
	&D3DXVECTOR3 (0.0f, 0.0f, 0.0f),
	&D3DXVECTOR3 (0.0f, 1.0f, 0.0f));

Теперь в структуру класса рамки добавим текстуру:

class CMainWnd : public CFrameWnd
{
private:
	LPDIRECT3D8             p_d3d;		// наш главный интерфейс 
	LPDIRECT3DDEVICE8	p_d3d_Device;		// наше устройство d3d8
	D3DDISPLAYMODE		d3ddm;		// способ отображения
	D3DPRESENT_PARAMETERS	d3dpp;		// параметры монитора
	LPDIRECT3DVERTEXBUFFER8 p_VertexBuffer;	// наш буфер вершин
	LPDIRECT3DTEXTURE8	textura001;		// наша текстура
	.	
	.
	.

Более подробно об этой структуре см. раздел Справка по DirectX: "Шаг 67 - Описание интерфейса IDirect3DTexture8". Так как мы создали указатель, то не забудем его удалить:

CMainWnd::~CMainWnd(void)
{
	_RELEASE_ (textura001);
	_DELETE_ (textura001);
	_RELEASE_ (p_VertexBuffer);
	_DELETE_ (p_VertexBuffer);
	_RELEASE_ (p_d3d_Device);
	_DELETE_ (p_d3d_Device);
	_RELEASE_ (p_d3d);
	_DELETE_ (p_d3d);
}

В конструкторе главного окна загрузим нашу текстуру и присвоим указатель на нее, добавьте перед закрывающей скобкой:

D3DXCreateTextureFromFile (p_d3d_Device, "01.jpg", &textura001);

Более подробно об этой функции см. раздел Справка по DirectX: "Шаг 68 - Текстурная функция D3DXCreateTextureFromFile". И, конечно, нам нужно не только загрузить в память, но и отобразить в нашей сцене:

p_d3d_Device->BeginScene ();
p_d3d_Device->SetVertexShader (D3DFVF_CUSTOMVERTEX);
p_d3d_Device->SetStreamSource (0, p_VertexBuffer, sizeof(CUSTOMVERTEX));
p_d3d_Device->SetTexture (0, textura001);
p_d3d_Device->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
p_d3d_Device->SetTextureStageState (0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
p_d3d_Device->DrawPrimitive (D3DPT_TRIANGLELIST, 0, 2);
p_d3d_Device->EndScene ();

Более подробно об этих функциях см. раздел Справка по DirectX:

Компилируем, запускаем. И видим, что стенка есть, текстуры нет... Все правильно, мы не указали как текстуре накладываться на наш объект:

Из рисунка видно, как спроецировать текстуру на наш объект. 0,0 - это начало координат, 1 - это максимум пикселей в текстуре по оси tu и tv. Точку 0,0 на текстуре у нас занимает вторая вершина первого треугольника, поэтому в структуре вершин здесь оставляем 0,0. 0,1 - занимает первая вершина первого треугольника, а также первая вершина второго треугольника. 1,0 - соответствует третьей вершине первого треугольника и вторая вершина второго треугольника. А 1,1 - это третья вершина второго треугольника, поэтому структура у нас выглядит следующим образом:

CUSTOMVERTEX g_Vertices[] =
{
	{ -100.0f,   0.0f,  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,},
	{ -100.0f, 180.0f,  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,},
	{  100.0f, 180.0f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,},

	{ -100.0f,   0.0f, 0.0f, 0.0f, 0.0f,  0.0f, 0.0f, 1.0f,},
	{  100.0f, 180.0f, 0.0f, 0.0f, 0.0f,  0.0f, 1.0f, 0.0f,},
	{  100.0f,   0.0f, 0.0f, 0.0f, 0.0f,  0.0f, 1.0f, 1.0f,},
};

Компилируем и запускаем :) Yes, у нас это получилось :) но доски слишком широкие... Размножим текстуру по оси tu. Вместо выделенных единиц поставьте 6.0f. Скомпилируйте и запустите свое приложение. Симпатично :)

Самый важный атрибут у текстуры - это размер изображения. Так как именно из за него зависит скорость игрушки. Размер изображения должен быть 32х32, 128х256 или 4х4, т.е. кратный двум. Размер 320х240 не подходит и лучше не использовать... Я в данном шаге принебрег этим правилом, т.к. здесь скорость не столь важна...

Вывод: мы можем много что сделать с текстурой, комбинируя разными значениями: например, повернуть или заставить ее вращаться в реальном времени, сделать зеркальное отражение, размножить на поверхности и т.д. и т.п. Заставьте снова вращаться нашу сцену, замените флажок D3DCULL_NONE, скажем, на D3DCULL_CCW и посмотрите, что будет.


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Хавов Евгений Валерьевич - 1.09.2002