Программирование графических процессоров с использованием Direct3D и HLSL


Вывод сцены в текстуру


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

C++

LPDIRECT3DTEXTURE9 RenderTexture = NULL; LPDIRECT3DSURFACE9 RenderSurface = NULL;

Pascal

var RenderTexture: IDirect3DTexture9; RenderSurface: IDirect3DSurface9;

Следующий шаг заключается в создании текстуры. Это можно проделать, воспользовавшись, к примеру, функцией D3DXCreateTexture(). Первый аргумент функции это ссылка на устройство вывода; второй и третий параметры задают ширину и высоту создаваемой текстуры соответственно; четвертый аргумент определяет количество мип- уровней (в нашем случае мип-уровни не используются, поэтому передаем ноль); пятый параметр – флаги использования (в нашем случае необходимо передать константу D3DUSAGE_RENDERTARGET, указывающую на то, что текстура будет использоваться как поверхность вывода); шестой аргумент задает пиксельный формат текстуры (здесь, как правило, наиболее часто используются константы D3DFMT_R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5 и др.); седьмой параметр – это флаг месторасположения (хранения) текстуры (здесь передаем значение по умолчанию); и последний восьмой аргумент функции – это имя переменной, в которую будет возвращен результат. Ниже приводи тся пример создания текстуры размером 512х512 пикселей.

C++

D3DXCreateTexture(device, 512, 512, 0, D3DUSAGE_RENDERTARGET, D3DFMT_R8G8B8, D3DPOOL_DEFAULT, &RenderTexture);

Pascal

D3DXCreateTexture(device, 512, 512, 0, D3DUSAGE_RENDERTARGET, D3DFMT_R8G8B8, D3DPOOL_DEFAULT, RenderTexture);


Всевозможные операции с текстурой библиотека Direct3D производит через поверхности. Для того, чтобы получить базовую поверхность любой текстуры, нужно вызвать метод GetSurfaceLevel() интерфейса IDirect3DTexture9. Метод имеет два параметра: первый – это номер текстурного уровня (так как у нас уровень всего один, то передаем ноль), а второй – указатель переменную, в которой будет храниться поверхность.
C++RenderTexture->GetSurfaceLevel(0, &RenderSurface);
PascalRenderTexture.GetSurfaceLevel(0, RenderSurface);

И последний шаг в данной методике – это указание поверхности вывода. Этот шаг реализуется через вызов метода SetRenderTarget() интерфейса IDirect3DDevice9. Этот метод имеет два параметра: первый – это индекс поверхности вывода (так как у нас поверхность одна, то передаем нулевое значение); второй аргумент – поверхность вывода.
C++device->SetRenderTarget(0, RenderSurface);
Pascaldevice.SetRenderTarget(0, RenderSurface);

Как правило, подобный вызов производится непосредственно в процедуре вывода примитивов перед вызовом метода Clear(). Вывод на поверхность сопряженную с текстурой ничем не отличается от обычного способа. Единственное отличие заключается в том, что результат (вся сцена) будет "воспроизводиться" в текстуре. Для того, чтобы восстановить вывод сцены обратно в буфер отображения (back buffer), нужно вначале программы сохранить указатель на этот буфер в некоторую переменную.
C++
LPDIRECT3DSURFACE9 BackBuffer = NULL; … device->GetRenderTarget(0, &BackBuffer);
Pascal
var BackBuffer: IDirect3DSurface9; … device.GetRenderTarget(0, BackBuffer);

Затем необходимо вызвать метод SetRenderTarget(), и в качестве второго параметра передать ссылку на сохраненную поверхность вывода (back buffer).
C++device->SetRenderTarget(0, BackBuffer);
Pascaldevice.SetRenderTarget(0, BackBuffer);

Поверхность вывода, ассоциированную с текстурой можно в любой момент сохранить в файл на диске. Для этого можно воспользоваться функцией D3DXSaveTextureToFile(), которая имеет четыре параметра.


Первый аргумент – это указатель на строку, содержащую имя сохраняемого файла; второй параметр определяет формат графического файла (задается одной из следующих констант: D3DXIFF_BMP, D3DXIFF_JPG, D3DXIFF_TGA, D3DXIFF_PNG, D3DXIFF_DDS, D3DXIFF_PPM, D3DXIFF_DIB, D3DXIFF_HDR, D3DXIFF_PFM); третий аргумент – это ссылка на интерфейс IDirect3DBaseTexture9, содержащий нужную текстуру; и четвертый параметр представляет собой ссылку на структуру, определяющую палитру из 256 цветов. Ниже приведен пример сохранения поверхности вывода, ассоциированной с текстурой в файл на диске.
C++D3DXSaveTextureToFile("scene.bmp", D3DXIFF_BMP, RenderTexture, NULL);
PascalD3DXSaveTextureToFile('scene.bmp', D3DXIFF_BMP, RenderTexture, nil);


Содержание раздела