Книги

OpenGL / FPC - Глава 19

Эта глава посвящена загрузке битмап-изображений, которые присоединены к исполняемому файлу как ресурсы. Может возникнуть вопрос, почему я не рассказываю о внешних bmp-файлах, ведь это проще понять большинству новичков. Причина вот в чем: существует множество библиотек и модулей, которые подгружают bmp-файлы, TGA, JPG и файлы прочих форматов в память, и я не буду детально касаться этого — просто идите на www.freepascal.org и поищите соответствующие модули. С другой стороны, файлы ресурсов — это нечто совершенно другое, и не везде эта тема хорошо раскрывается.

Файлы ресурсов — это обычные файлы, которые связываются с исполняемыми. И совсем не важно, являются ли они графическими файлами, звуковыми или какими-нибудь еще. Поскольку они внедрены в исполняемый файл, к ним можно обращаться посредством WinAPI. Это дает нам практически все, что нужно — даже загрузку этих графических файлов в память. К сожалению, эти файлы должны быть в формате bmp, что делает исполняемые файлы довольно большими, но тут ничего не поделать.

И снова к вопросу "Зачем использовать ресурсные файлы?". Я бы сказал, что это — хороший способ включить данные в ваш исполняемый файл, делая ненужным использование внешних файлов или архивов. Вы сможете держать все в одном файле. Вам не придется маяться с подгрузкой внешний файлов, поскольку за вас все сделает WinAPI. Ну и, кроме того, иметь дело с ними сравнительно легко.

Так давайте приступим. Для тех из вас, кто никогда не работал с файлами ресурсов, сейчас будет краткая сводка о ресурсах в Windows. Ресурсные файлы пишутся похожими на скрипты. В действительности, ресурсные файлы сначала создаются в виде "ресурсного скрипта", и затем компилируется в "ресурсный файл", который, в свою очередь, FPC компонует в исполняемый. Но вначале нам следует скомпилировать ресурсный скрипт.

К счастью для нас, FPC снабжается компилятором ресурсов, который называется "WindRES". Но я, к сожалению, не буду использовать WindRES в этом учебнике. Вместо этого я пользуюсь GoRC. Его можно достать с www.jorgon.freeserve.co.uk. Он совсем небольшой, и использовать его проще. Кроме того, ресурсные скрипты для WindRES и для GoRC немного отличаются. Так что пользоваться кодом из этого учебника для WindRES не получится. Приношу извинения.

Но, к счастью, нам не надо углубляться в науку о написании ресурсных скриптов, так как для добавления bmp-файла нужна всего лишь одна строка. Если вам интересны ресурсные файлы как таковые, загляните в учебник по Win32/ FPC.

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

 2 BITMAP	texture.bmp

Сохраним этот файл как "source19.rc". Посмотрим на эту строку. Первое число — это ID ресурса. По этому ID можно обращаться к ресурсам из вашего приложения. Следующее — это тип ресурса. В нашем случае стоит "BITMAP", ведь мы включаем в качестве ресурса битмап-изображение. Это важно указать, ибо bmp-файл может быть включен и как простой файл, без определенного типа. Но в этом случае Windows не сможет обращаться к нему посредством функций WinAPI для работы с битмап-изображениям. А третий параметр — имя файла. Конечно, имя "texture.bmp" можно заменить на имя того файла, который вы хотите подключать.

Теперь нужно скомпилировать ресурсный скрипт. GoRC — это консольное приложение, так же, как и FPC. Это значит, что вам необходимо ввести команду для компиляции вручную. Конечно же, в вашем любимом текстовом редакторе можно вызвать GoRC (не так ли??). Но я расскажу, как сделать все "ручками".

Откройте новое окно DOS. Смените каталог на тот, где располагается. Введите "GoRC /r source19.rc". Конечно, вам придется указать полный путь к GoRC, или же GoRC должен располагаться в том же каталоге, что и ресурсный скрипт. Если все прошло правильным образом, то в этом каталоге должен появиться файл "source19.res". Если нет, проверьте, работает ли GoRC и имеется ли в том каталоге скрипт и bmp-файла.

Сейчас у нас есть скомпилированный ресурсный файл. Обратите внимание, что его размер — примерно такой же, как и у bmp-файла. Но как же указать FPC, что его следует компоновать в наше приложение? Это просто. Добавьте следующую строку и файл исходного кода (желательно после раздела перечисления используемых модулей).

 {$r source19.res}

Встретив это, FPC скомпонует указанный ресурсный файл в исполняемый. При этом ваш bmp-файл будет внедрен в exe-файл. Конечно же, размер приложения увеличится примерно на размер bmp-файла.

Еще немного о включении bmp-файлов. Во-первых: помните, что текстуры должны иметь размер 2^n, что означает 64*64, 128*128, 256*256 и так далее. Во-вторых, проследите, чтобы bmp-файлы имели битовую глубину больше, чем 8 бит. Если у битмапа 8 бит (что означает 256 цветов), они содержат цветовую палитру, а не непосредственно RGB область. Так что убедитесь, что вы используете 24/32 битные bmp-файлы.

Теперь можно загружать bmp-файл как текстуру. Это делать очень просто, если вы знакомы немного с WinAPI. Как обычно, вам потребуется хэндл (handle) и структура (structure), которые будут заполняться значениями и содержимым.

procedure Texture_Init();
var
  i : longint;
  gBitmap : hBitmap;   // handle
  sBitmap : Bitmap;    // structure
begin

Теперь нужно связать изображение с нашим хэндлом. Обратите внимание, что мы НЕ загружаем реальное содержимое bmp-файла, хоть имя функции и указывает на это. Это делается во второй строке. Здесь мы заносим в bitmap-структуру содержимое bmp-файла, то есть ширину, высоту, битовую глубину и, разумеется информацию о пикселях.

 hbitmap := LoadImage(GetModuleHandle(nil), MAKEINTRESOURCE(2), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
 GetObject(hbitmap, sizeof(sbitmap), @sbitmap);

Теперь создаем текстуру обычным способом. Сначала сообщаем OpenGL, как выравниваются данные, и как их распаковывать. А затем обратите внимание, как мы загружаем текстуру в память OpenGL. Мы пользуемся только содержимым bitmap-структуру. Нет никакой необходимости в еще одном указателе.

 glEnable(GL_TEXTURE_2D);
  glGenTextures(1, @TextureID);
  glBindTexture(GL_TEXTURE_2D, TextureID);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  glTexImage2D(GL_TEXTURE_2D, 0, 3, sbitmap.bmWidth, sbitmap.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, sbitmap.bmBits);
 glBindTexture(GL_TEXTURE_2D, TextureID);

Вот и все. bmp-изображение загружено в память OpenGL и его можно использовать как обычную текстуру. Скачайте архив с примером. В нем присутствуют несколько дополнительных файлов (один bmp-файл и один ресурсный файл) вместе с исходным кодом.

Актуальные версии
FPC3.2.2release
Lazarus3.2release
MSE5.10.0release
fpGUI1.4.1release
links