Direct draw термины и концепции интерфейсы directdrawsurface


Direct draw термины и концепции интерфейсы directdrawsurface

Начнем написание нашей программы, выбрав «Win32 Application» в диалоге создания нового проекта среды Visual C++. В первом окне мастера выберем «Simple Win32 Application» и позволим Visual C++ создать функцию WinMain. Код, сгенерированный мастером, выглядит так:

Теперь, когда у нас есть основная функция программы, мы должны создать главное окно, это нам нужно для того, чтобы получать сообщения, посланные нашему приложению операционной системой. Даже если вы работаете с полноэкранным приложением DirectX вам все равно нужно создавать это окно, иначе приложение не получит необходимые для работы сообщения. Разместим код создания окна в отдельной функции, которая будет называться InitWindow.

Первое, что делает эта функция, — это регистрирует класс окна в среде Windows. После заполнения структуры WNDCLASS информация о регистрируемом классе передается в функцию RegisterClass. Заметим, что впоследствии нам понадобится хэндл приложения, поэтому сохраним его в глобальной переменной g_hInst. Еще одна переменная будет содержать хэндл основного окна программы (которое мы собственно и создаем). Обе переменные объявлены чуть выше определения функции WinMain:

Не забудьте присвоить значения этим переменным, для этого в самом начале функции WinMain добавьте следующий фрагмент кода:

Как вы уже, наверное, заметили, функция InitWindow, которую мы создали чуть выше, возвращает хэндл создаваемого окна, чем мы и воспользуемся. На этапе написания функции InitWindow мы не обсудили назначение параметра lpfnWndProc. Этот параметр содержит ссылку на функцию, которая будет обрабатывать сообщения, посылаемые нашему приложению операционной системой. Эта функция будет вызываться операционной системой каждый раз, когда приложению посылается какое-либо сообщение (типа нажатия клавиши, сообщения от мыши и т.д.). Вот как выглядит скелет функции WndProc:

Итак, ваше приложение почти готово к запуску, единственное, что еще нужно сделать — реализовать цикл обработки сообщений. Для того, чтобы приложение смогло «отловить» сообщения, нам нужно вызвать функцию, которая будет обрабатывать пришедшие сообщения. Если мы получили одно из таких сообщений, нам нужно обработать его в функции WndProc. Если никаких сообщений не поступало, мы можем использовать «свободное время» для выполнения каких-либо фоновых вычислений или для задач DirectX. Этот процесс называется idle processing — обработка во время простоя. Цикл обработки сообщений нужно вставить прямо за инициализацией наших глобальных переменных.

В цикле проверяется, есть ли еще в очереди сообщения, которые нужно обработать. Это выполняется вызовом функции PeekMessage. Если функция возвращает истину, мы вызываем функции TranslateMessage и DispatchMessage, что вызывает обработку очередного сообщения. Если сообщений в очереди нет, вызывается функция ProcessIdle. Мы напишем эту функцию так, что она будет обновлять картинку на экране. Вот как определяется эта функция:

Итак, основа нашего приложения готова. Если вы откомпилируете и запустите приложение, вы увидите черное окно, которое занимает весь экран.

Инициализация DirectX и DirectDraw

Теперь можно приступить к такой задаче, как инициализация DirectDraw. Сначала разберем концепцию поверхностей и флиппинга (переключения, flipping) поверхностей. Все графические построения, выполняемые DirectDraw, основаны на структурах, называемых поверхностями (surface). Поверхности — это области памяти, содержащие графику, которые управляются и используются вашим приложением. Все, что нужно нарисовать на экране, сначала должно быть создано на поверхности.

Итак, вся графика хранится в памяти в структурах, называемых поверхностями. Фактически, в приложениях DirectDraw, область, которую мы видим на экране, тоже рассматривается как поверхность, называемая видимой поверхностью или фронт-буфером (frontbuffer). Вместе с видимой поверхностью ассоциируется поверхность, называемая невидимой поверхностью или бэк-буфером (backbuffer). Эта поверхность содержит информацию, которая будет показана пользователю в следующем кадре. Предположим, пользователь видит первый объект на экране в позиции (10,10) , а второй объект — в позиции (100,100). В процессе перемещения первый объет должен оказаться в позиции (12,10), второй объект — в позиции (102, 10). Если мы будем формировать картинку прямо на видимой поверхности, возникнут проблемы с синхронизацией (т.е. пользователь увидит, что сначала переместился первый объект, а затем — второй, но реально они должны перемещаться одновременно, т.е. синхронно). Для решения этой проблемы мы создаем каждый следующий кадр на невидимой поверхности. После совершения всех передвижений в бэк-буфере мы перемещаем информацию с невидимой поверхности на видимую. Этот процесс называется флиппингом и он очень напоминает процесс создания мультипликационных фильмов (когда мы используем множество картинок, нарисованных на бумаге).

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

Теперь, когда у вас есть некоторое представление об основах DirectDraw, начнем писать код, относящийся непосредственно к DirectX-овой части нашей программы. Первое, что нужно сделать — включить заголовочный файл DirectDraw в головной файл проекта. Просто вставьте следующую строчку в самом начале файла:

Также проекту нужно «подсказать», какие библиотеки нужны для работы DirectDraw. Идем в меню Project, подменю Settings. Выберите закладку «Link» и добавьте следующие библиотеки в поле «Object/Library Modules» (конечно, если их там уже нет)

Теперь нам нужно создать в программе новую функцию. Эта функция будет называться InitDirectDraw и основной ее целью будет выполнение подготовительных операций — создание объекта DirectDraw и создание двух поверхностей (видимой и невидимой).

Вы, наверное, заметили, что в коде используются несколько необъявленных ранее переменных с префиксом «g_» (глобальная переменная). Так как указатели на видимую и невидимую поверхность будут использоваться во всей нашей программе, поместим их в глобальные переменные. Еще одна очень важная переменная — в ней мы будем хранить объект DirectDraw — g_pDD. Этот объект используется при создании всех остальных объектов, используемых в DirectDraw. Итак, в самом начале нашего кода добавим еще несколько строчек:

Вернемся к функции InitDirectDraw. Первое, что в ней делается — создается объект DirectDraw. Для этого используется функция DirectDrawCreate, которая объявлена в файле ddraw.h. Наиболее важны два параметра этой функции — второй и третий. Второй параметр — это ссылка на переменную, в которой мы будем хранить указатель на объект (в нашем случае это переменная g_pDD). В третьем параметре передается идентификатор версии объекта DirectDraw. Это позволяет работать с ранними версиями DirectDraw после инсталляции новых версий SDK. Например, можно работать с объектами DirectX 7, используя DX SDK 8.1.

Как вы, наверное, заметили, результат функции сравнивается с константой DD_OK, которая означает, что функция выполнилась успешно (это справедливо для всех функций DirectDraw). Важно проверять каждое значение, возвращаемое функциями DirectDraw. Если значение не равно DD_OK, функция InitDirectDraw возвращает -1. В этом случае можно предположить, что на компьютере пользователя не установлена нужная версия DirectX и выдать предупреждающее сообщение (позднее будет продемонстрировано, как это сделать).

Второй вызов функции — SetCooperativeLevel. Эта функция используется для того, чтобы «сообщить» DirectX, каким образом мы собираемся работать с экраном — в полноэкранном режиме или оконном и т.п. Все доступные опции этой функции приведены в документации к DirectX. Опять же результат функции проверяется на корректность.

Третья функция — SetDisplayMode. С помощью этой функции можно установить необходимое разрешение экрана нашего приложения. В приведенном фрагменте устанавливается полноэкранный режим 640×480. В качестве третьего параметра в функцию передается глубина цвета. От этого параметра зависит максимальное количество цветов, отображаемое программой.

После процедур инициализации нам нужно создать две поверхности, которые будут использованы для вывода графики на экран. Сначала инициализируется видимая поверхность. Для создания поверхности в DirectDraw нужно правильно инициализировать поля структуры DDSURFACEDESC2. Очень важно сначала очистить память, занимаемую структурой, функцией ZeroMemory или memset (иначе в некоторых случаях могут возникнуть проблемы). Создавая видимую поверхность, параметру dwflags нужно присвоить значение DDSD_BACKBUFFERCOUNT, указывающее, что поверхность видимая и ей соответствует невидимая поверхность. Параметр ddsCaps.dwCaps нужно инициализировать значением DDSCAPS_PRIMARYSURFACE. Т.к. мы будем осуществлять флиппинг поверхностей, нужно указать параметры DDSCAPS_FLIP и DDSCAPS_COMPLEX.

После заполнения структуры DDSURFACEDESC2 нужно вызвать метод CreateSurface глобального объекта DirectDraw, передать ему структуру, которую мы только что заполнили, и ссылку на переменную, которая будет хранить указатель на видимую поверхность.

После создания видимой поверхности нам нужно получить ссылку на невидимую поверхность, ассоциированную с фронт-буфером. Это можно выполнить, вызвав метод GetAttachedSurface видимой поверхности. В качестве параметра нужно указать структуру DDSCAPS2.

Итак, мы завершили написание функции инициализации DirectDraw, теперь ее нужно вызвать из основной программы. Вот как это выглядит:

Обратите внимание, как обрабатывается отрицательный код возврата — мы сообщаем пользователю, что программа не может продолжать работу из-за неверной версии DirectX.

Здесь вызывается еще одна функция — CleanUp — которую мы еще не описали. Эта функция должна удалять все созданные объекты DirectX. Все объекты удаляются вызовом метода Release. Вот реализация этой функции:

Прежде, чем мы откомпилируем и запустим приложение, вставьте следующий фрагмент в функцию WndProc, в оператор switch обработки сообщений:

Этот фрагмент кода дает возможность выхода из программы по клавише ESCAPE. Теперь откомпилируйте и запустите приложение и убедитесь, что программа переходит в полноэкранный режим 640×480.

Блиттинг графики

Теперь мы займемся рисованием на невидимой поверхности и флиппингом поверхностей, что в конечном итоге создаст на экране анимированную картинку. Для создания анимации мы будем использовать битмап с несколькими изображениями машины. Для создания спрайта в DirectDraw нам нужно сохранить битмап на отдельной поверхности (которую мы будем называть тайлом или закадровой поверхностью), которую мы затем будем копировать на невидимую поверхность. Для удобства манипулирования тайловыми поверхностями мы создадим класс cSurface. Щелкните правой кнопкой мыши в окне ClassView среды Visual C++ и выберите пункт Create New Class (или выберите пункт меню «Insert» -> «New Class. «). Тип класса оставьте неизменным — Generic Class, а в качестве имени укажите cSurface.

Начнем описание методов нашего класса. Основная переменная будет иметь тип LPDIRECTDRAWSURFACE7, она будет служить для хранения объекта DirectDraw Surface (поверхность DirectDraw). Также мы должны хранить длину и ширину поверхности. Еще одно поле класса — m_ColorKey — подробнее о нем мы поговорим позднее. Вот как выглядит описание переменных создаваемого класса:

Первая функция, которая будет создана в классе — функция Create. Эта функция будет создавать объект типа поверхности DirectX. Вот реализация функции Create:

Как вы наверное заметили, процесс создания тайловой поверхности мало чем отличается от процесса создания видимой поверхности. Вся разница заключается в заполнении полей структуры DDSURFACEDESC2. Параметр dwFlags указывает, что мы будем заполнять поля dwCaps, dwWidth и dwHeight и что их нужно учитывать при создании поверхности. Параметр dwCaps, равный DSCAPS_OFFSCREENPLAIN, указывает, что поверхность закадровая, т.е. невидима. Указывая флаг DDSCAPS_VIDEOMEMORY, мы даем понять, что хотим создать поверхность в видеопамяти.

Проверка ошибок заключается в проверке результата на значение DDERR_OUTOFVIDEOMEMORY, если на компьютере пользователя установлена старая видеокарта с небольшим количеством памяти, можно указать DDSCAPS_SYSTEMMEMORY и попробовать создать поверхность в системной памяти. Процесс блиттинга из системной памяти в видеопамять существенно медленнее, чем блиттинг видеопамять — видеопамять, однако если видеопамяти мало, приходится прибегать и к нему.

В конце функции мы осуществляем проверку параметра dwColoKey. Это нужно делать, если мы работаем с поверхностями, у которых задан цветовой ключ. Цветовой ключ — цвет, который не отображается на заданной поверхности. Например, мы хотим копировать космический корабль на фон, изображающий звездное небо. При этом мы не хотим видеть черный фон изображения космического корабля, поэтому мы можем задать цветовой ключ таким образом, что будет показан только космический корабль, но не фон. Вам нужно позаботиться, чтобы фон ваших картинок не содержал цветов, которые используются в самой картинке.

Теперь мы займемся созданием еще одной функции, загружающей битмап на поверхность DirectX. Для этого воспользуемся некоторыми функциями GDI. Так как нам нужно загрузить всего одну картинку, функция не будет влиять на общую производительность приложения. Функция LoadBitmap выглядит следующим образом:

Если вы хотя бы немного работали с функциями GDI, этот фрагмент не покажется вам слишком сложным. Во-первых, нужно вызвать метод Restore переменной m_Surface. Это нужно для восстановления памяти, которая может быть освобождена DirectDraw (если возникает такая ситуация, любое обращение к объекту m_Surface возвращает код ошибки DERR_SURFACELOST). После восстановления памяти мы создаем DC и загружаем картинку из ресурсов. Затем битмап копируется на поверхность с помощью функции StretchBlt. Также мы сохраняем информацию о битмапе в структуре m_srcInfo. Эта структура используется в случае, если поверхность «потеряется», так что мы всегда можем восстановить поверхность и изображение, хранящееся на ней.

Илон Маск рекомендует:  Что такое код imap_rfc822_parse_adrlist

Предпоследняя функция, которую нам предстоит реализовать, — функция Draw, которая используется для «рисования» части одной поверхности на части второй. Чаще всего вам придется рисовать на невидимой поверхности, однако метод Draw работает с любыми видами поверхностей.

Алгоритм работы этой функции очень прост. Вначале мы создаем переменную типа прямоугольник (rect) и заполняем ее информацией о позиции и размерах исходной картинки, которую мы хотим поместить на поверхность. После этого мы вызываем метод объекта поверхности BltFast и помещаем картинку на поверхность. Посмотрите, как используется информация о цветовом ключе поверхности. Блиттинг поверхностей, не имеющих цветового ключа, выполняется намного быстрей, чем поверхностей, у которых задан цветовой ключ, так что используйте цветовые ключи только когда это действительно необходимо. Как вы заметили, рисование происходит в бесконечном цикле. Это сделано для того, чтобы в случае потери поверхности мы смогли ее восстановить и повторить операцию блиттинга.

И, наконец, функция Destroy создана для освобождения ресурсов DirectDraw, занимаемых приложением. В нашем случае мы вызываем метод Release объекта m_Surface.

В прилагаемом исходном коде вы увидите несколько дополнительных методов класса cSurface, однако для целей данной статьи описанных методов вполне достаточно. Откомпилируйте приложение.

Рисование на невидимой поверности с помощью класса cSurface

Следующим шагом в написании нашего приложения будет создание экземпляра класса cSurface и копирование информации с получившейся поверхности на невидимую поверхность. Для этого нам нужно включить заголовочный файл с описанием класса cSurface перед объявлением функции WinMain.

Теперь объявим переменную, которая будет хранить экземпляр нашего класса. Разместите следующее объявление ниже объявлений глобальных переменных:

После этого добавьте в приложение ресурс — картинку из файла bmp_bigcar_green.bmp . Создайте идентификатор (ID) ресурса с именем «IDB_GREENCAR«.

Итак, у нас есть экземпляр класса, нужно вызвать методы создания и загрузки картинки. Этот фрагмент кода должен вызываться после вызова функции InitDirectDraw.

Те объекты, которые были созданы нами во время выполнения программы, нужно уничтожить. Для этого достаточно вызвать их метод Destroy. Для выполнения всех «чистящих» действий создадим функцию CleanUp.

Сейчас мы создали и инициализировали нужные объекты и реализовали код для освобождения памяти, выделенной для поверхностей, так что можно приступать к «рисованию» в бэк-буфере и отображению картинки на видимой поверхности. Напомню, что все эти действия выполняются в функции ProcessIdle.

Этот фрагмент кода рисует первую картинку машины по центру невидимой поверхности и осуществляет флиппинг невидимой и видимой поверхности каждый раз при вызове функции ProcessIdle. Давайте чуть изменим код и реализуем анимированное движение машины:

Здесь мы создаем 3 статических переменных. Первые используются для изменения позиции копируемой части исходной картинки. Таким образом мы можем создать эффект анимации, последовательно проходя от кадра 1 до 20. Третья переменная, iLastBlit, хранит результат выполнения функции GetTickCount. Этот результат используется для того, чтобы задержать кадр по меньшей мере на 50 миллисекунд на экране, что нужно для плавного перемещения картинки. Можете удалить фрагмент кода и посмотреть, что получится (на хорошем компьютере картинка будет вращаться очень быстро).

DirectX и Delphi — введение

Как обычно, начну с оговорок.
Первое – для меня большая проблема перевести некоторые термины. Поэтому я думаю может и не стоит их переводить. :-) Вот список терминов, которые вызывают у меня трудности с переводом:

  • blitting — blit сокращение от «bit block transfer» пересылка блоков данных из одной области видеопамяти в другую.
  • flip – переключение между буферами видеопамяти
  • Surface – «поверхность» – область видеопамяти

Второе – разговор идет о использовании DirectDraw в Delphi. Для того, чтобы воспользоваться DirectX вообще и DirectDraw в частности, нужно, чтобы во-первых DirectX был установлен на компьютере (скачать его можно у Microsoft например, впрочем я не думаю, что для читателя будет проблемой его найти), во-вторых нужны файлы заголовков DirectX – их существует немало, я по-прежднему считаю компонент DelphiX от Hiroyuki Hori – превосходным, кроме того, существует официально поддерживаемые Borland’ом заголовки DirectX, составленные в рамках проекта «JEDI» – скачать их можно с (http://www.delphi-jedi.org/).

Третье – неплохо если Вы имеете некоторое общее представление о работе видеоадаптера (ну очень общее – тонкости не нужны) и еще более общее о COM-технологии (всего-то нужно знать что такое COM- Interface, впрочем и это не обязательно).

DirectDraw – интерфейс DirectX, предназначенный, по существу, для управления видеопамятью.

Прелесть однако заключается в том, что с DirectDraw доступ к видеопамяти становится не зависимым от типа используемой видеоплаты (ну или почти не зависимым). DirectDraw обращается к апаратуре посредством hardware abstraction layer (HAL) – (уровня абстагирования от аппаратуры). Кроме того с помощью hardware emulation layer (HEL) (уровня эмуляции аппаратуры) те возможности, которые не реализованы в данной видеокарте эмулируются программно (к сожалению тут есть пара исключений). Благодаря такому подходу жизнь программиста становится легче и веселее – если, например, видеокарта поддерживает hardware blitting – DirectDraw использует эту возможность через HAL – если нет – эмулирует через HEL (естественно эмуляция всегда медленнее). На рисунке из SDK показаны отношения между DirectDraw, GDI, HAL и HEL.

Как видно из рисунка DirectDraw находится вне GUI. DirectDraw может предоставлять области памяти, с которыми он работает в виде контекста устройства (device context, привычный для Windows-программиста), что позволяет использовать функции GDI для работы с ним (например, выводить текст с помощью функции TextOut)

DirectDraw можно использовать как при рисовании в окне Windows так и при работе в полноэкранном режиме. Я пока буду говорить только о полноэкранном режиме (с эксклюзивным уровнем кооперации).

Режим определяет размер видимой области экрана в пикселах и число бит, требуемых для представления одного пиксела (“глубина цвета ”) (практически все мониторы поддерживают например режим 640ґ480ґ8). Чем больше ширина и высота экрана в пикселах, и чем больше бит требуется для представления одного пиксела, тем больше видеопамяти требуется для режима.

Кроме того видеорежимы бывают палитровыми (palettized) и безпалитровыми (non-palettized). В палитровых режимах “глубина цвета” означает число элементов палитры для данного режима, например 8-битовый палитровый режим означает, что используется палитра, размером 256 элементов. В безпалитровом режиме “глубина цвета” означает число бит для представления цвета (8 бит – 256 цветов, 16 бит – 65535 цветов и т.д.)
Чтобы выяснить какие режимы поддерживает ваша видеокарта можно использовать интефейс IDirectDraw4::EnumDisplayModes.

выясним все поддерживаемые видеорежимы

Чувствуете почему я так люблю Hiroyuki Hori с его компонентом DelphiX? :-) Действительно проще – но, увы, документация у DelphiX очень скудная (и по большей части на японском). Вообще говоря, наверное полезно изучить “классический” способ работы с DirectDraw от JEDI – потом легче пользоваться и DelphiX.

Установить видеорежим можно методом IDirectDraw4::SetDisplayMode.

Восстановить тот видеорежим, что был установлен до вызова SetDisplayMode можно функцией IDirectDraw4::RestoreDisplayMode. Впрочем, для программ использующих полноэкранный режим это не так уж важно – прежний режим будет восстановлен автоматически.

Кстати пример с JEDI-заголовками хорош тем, что демонстрирует создание объекта IDirectDraw получение ссылки на интерфейс IDirectDraw4 вызовом метода QueryInterface из IDirectDraw (IDirectDraw без номера – базовый (и самый старый) интерфейс DirectDraw; IDirectDraw4 – интерфейс из DirectX 6). Вообще объект IDirectDraw – это самая, что ни на есть, сердцевина DirectDraw – он представляет собой некую абстракцию над видеоадаптером – с помощью его методов создаются все остальные объекты DirectDraw (Surface’ы, палитры и т.д.). В принципе можно создавать больше одного объекта IDirectDraw – если у Вас больше одного видеоадаптера и несколько мониторов – в таком случае Вы ровно во столько раз круче меня, на сколько число Ваших видеоадаптеров больше 1-го :-) (для знатоков COM-технологии – для этого при создании объекта DirectDraw нужно передать GUID другого дисплея). Если же монитор у Вас один Вы можете создавать несколько объектов DirectDraw – все они будут управлять одним и тем же видеоадаптером – но мы этот случай рассматривать не будем.

В случае же если Вы используете Hori’вский компонент DelphiX – мучения с инициализацией и деинициализацией сводятся к нулю – достаточно просто разместить на форме компонент DXDraw – он сам позаботится о мелочах жизни, вроде create и release. :-)

Итак, переключаться между видеорежимами мы научились.

Поговорим теперь о Surface’ах. (моя попытка найти хороший русский эквивалент этому слову, не увенчалась успехом). Surface (объект DirectDrawSurface) – в буквальном переводе поверхность, представляет собой линейный участок в видеопамяти. (впрочем можно создавать Surface’ы и в системной памяти – но мы на этом не станем задерживаться) По умолчанию Surface создается так, чтобы получить максимальное быстродействие – в видеопамяти, если ее не хватает – в нелокальной видеопамяти (для плат AGP) а если и ее не хватает то в системной памяти (этот случай самый медленный). Объект DirectDrawSurface кроме указателя на область видеопамяти содержит несколько очень полезных методов (и зверски скоростных) для быстрого переноса квадратика видеоизображения из одного участка Surface’а в другой (blitting), для быстрой смены одного Surface’ а на экране другим – fliping, для работы с палитрами и спрайтами и др.

Ну как удалось мне вас заинтересовать? Ну тогда давайте разберемся – как эти самые замечательные Surface’ы создавать. Перво-наперво скажем что у каждого Surface’а должен быть размер — ширина и высота. Кроме того Surface’ы устроены так, что между началом одной строчки и другой расстояние не всегда равное ширине. Скажем мы создали Surface 640X480X8 – казалось бы между первой строчкой и второй ровно 640 байт – ан нет. Может 640 байт а может и больше (это завист от того парня, который писал драйвер Вашего видеоадаптера). Расстояние между строчками в байтах называется Pitch – переводится как шаг. Почему этот самый Pitch не всегда равен ширине видно из рисунка:

Видите – справа от нашего Front-bufera может быть какой-то кэш, если Вы вздумаете писать напрямую в видеопамять – писать туда (в кэш) строго не рекомендуется (за последствия никто не ручается). Кроме того Pitch, в отличие от ширины измеряется в байтах а не в пикселах.

Раз уж заговорили, про Front-bufer’ы – скажем уж и про то, что один Surface, называемый PrimarySurface, является главным — это тот самый Surface, который был виден на экране в момент когда мы начали создавать эти самые Surface’ы.

Surface’ы могут быть обьединены в так называемые flip-цепочки. Когда происходит flip между Surface’ами – тот Surface, что сейчас на экране, заменяется следующим в цепочке, на следующем flip’е – этот – следующим и т.д. – если дошли до последнего в цепочке – то он заменяется на первый. Ну в обычной жизни цепочка может состоять из всего двух Surface’ ов – при каждом они просто flip’е сменяют друг друга. Обратите внимание – при flip’е смена Surface’ов происходит не в результате пересылки всего их содержимого, а просто в результате изменения указателей на области видеопамяти в видеоадаптере – поэтому flip выполняется очень быстро. (Исключение может быть только в случае если Вы создали столько Surface’ов, что они не поместились в видеопамяти – тогда за дело возьмется HEL – бедняге придется все это эмулировать и скорость будет – не ахти). C помощью flip можно создавать анимацию, выводим какую-то картинку, затем в BackBuffer’e – чуть-чуть меняем эту картинку, вызываем flip, чуть-чуть меняем картинку в BackBuffer’e, вызываем flip и т.д. в цикле.

Вот пример создания Flip-цепочки из двух Surface’ов, обьектов IDirectDrawSurface4.

(Ссылки на два созданных Surface’а сохраняются в переменных FPrimarySurface и FbackSurface)
(этот пример взят из моей демо-программульки, которую Вы может скачать здесь 169K)

Создали Surface’ы. Теперь было бы интересно что-нибудь на них нарисовать. Интересно также попробовать писать прямо в видеопамять.
Получить указатель на область видеопамяти Surface’а можно вызвав метод Lock – он вернет указатель в структуре типа TDDSURFACEDESC2, которую получает в качестве параметра.

С фантазией у меня всегда было не очень – поэтому просто заполню всю область Surface’ов одним цветом, записав в видеопамять одно и тоже значение.

Обратите внимание — какой я аккуратный – перехожу между строчками, учитывая Pitch. Да кстати – я просто демонстрирую как обратится к каждому байту видеопамяти Surface’a на самом деле если нужно закрасить весь Surface одним цветом то заносить значения в каждый байт слишком медленно – для этого можно воспользоваться методом IDirectDrawSurface4.Blt, передав ему флаг DDBLT_COLORFILL. Кроме того можно выводить на Surface и привычными функциями GDI – TextOut’ом например:

Небольшое лирическое отступление – между вызовами LOCK и UNLOCK, а также между GetDC и ReleaseDC выполнение всех других программ останавливается (в том числе и отладчика). Отсюда выводы – первое – не стоит делать что-то слишком долго между этими вызовами, второе, отладить программу пошагово между этими вызовами – невозможно (если только Вы не вооружились Kernel-debuger’ом).

Теперь попробуем flip’ануть наши Surface’ы. Переключимся на другой Surface

Метод Flip может отказаться flip’овать и вернуть, среди прочих, такие коды ошибок:

  • DDERR_NOEXCLUSIVEMODE – этот код возврата означает, что наша программа потеряла эксклюзивный режим. Произойти такое может, если мы flip’уем в цикле по таймеру, а пользователь зачем-то ушел из нашей программы, свернув ее или нажав Alt-TAB. В таком случае, чтобы зря не тратить процессорные циклы, лучше подождать его возвращения, вызывая функцию Sleep(0) или WaitMessage.
  • DDERR_SURFACELOST – потеря Surface’ов пользователь уходил, но вернулся, Surface’ы нужно забрать назад, вызвав IDirectDraw4.RestoreAllSurfaces, содержимое их придется восстановить.

Все вышесказанное касается классического стиля использования DirectDraw в стиле С от JEDI. Поклонники же Hori’вского набора DelphiX могут поэкспериментировать c Surface’ами используя TDXDraw.DDraw.SurfaceCount, TDXDraw.DDraw.Surfaces, TDXDraw.Flip – вместе с набором компонент распространяются отличные примеры.

Я очень рад, что Вы дочитали до этого места (если Вы просто пролистали в конец, не читая, сделайте вид, что это не так, порадуйте меня, старика) :-).
На этом пока все. Если Вы заинтересовались – скачайте демо-программку и поэкспериментируйте.

Пишите мне – aziz@telebot.com или error@softhome.net – с удовольствием приму Ваши пожелания и предложения (особенно если предложите какую-нибудь работу) :-).

Copyright © 2004-2020 «Delphi Sources». Delphi World FAQ

Direct draw термины и концепции интерфейсы directdrawsurface

Приняв к сведению все эти описания DirectDraw, давайте познакомимся с некоторыми терминами и концепциями, составляющими неотъемлемую часть используемого жаргона. Мы начнем с простейших, но основных понятий, которые относятся к графике вообще, а затем перейдем к специфике DirectDraw.

Видеорежимы

Видеорежимом называется набор параметров, поддерживаемый аппаратурой видеокарты (видеоадаптера) и позволяющий организовать вывод графического изображения. Самым известным атрибутом видеорежима является разрешение экрана. По умолчанию в Windows используется видеорежим с разрешением 640×480. Это означает, что на экране выводится 640 пикселей по горизонтали и 480 пикселей по вертикали. Также часто встречаются видеорежимы с разрешением 800×600 и 1024×768. Некоторые видеокарты поддерживают так называемые режимы ModeX. Типичный режим ModeX имеет разрешение 320×200.

Видеорежимы также различаются по глубине пикселей (pixel depth). Этот параметр определяет количество различных значений, принимаемых отдельным пикселем, и, следовательно, количество отображаемых цветов. Например, в видеорежиме с глубиной пикселей в 8 бит каждый пиксель может иметь один из 256 различных цветов. В режимах с 16-битной глубиной пикселей поддерживается отображение до 65536 цветов. Глубина пикселей обычно равна 8, 16, 24 или 32 битам.

Видеорежимы реализуются специальным устройством, установленным на компьютере, — видеокартой. На видеокарте устанавливается отдельная память, не входящая в основную память компьютера. Память, установленную на видеокарте, мы будем называть видеопамятью, а обычную память (RAM) — системной памятью. Объем памяти, необходимой для поддержки определенного видеорежима, определяется разрешением и глубиной пикселей в этом режиме. Например, для видеорежима 640×480×8 (640×480 пикселей, каждый из которых имеет глубину в 8 бит) требуется 307300 байт. Видеорежим 1024×768×16 требует 1572864 байт. Для поддержки видеорежимов используется видеопамять. Следовательно, режимы, поддерживаемые конкретной видеокартой, ограничиваются объемом установленной видеопамяти. Скажем, режим 1024×768×16 не поддерживается видеокартами с 1 Мбайт памяти, потому что для него такой объем памяти недостаточен.

Одна из ключевых возможностей DirectDraw — переключение видеорежимов. Она позволяет приложению DirectDraw обнаружить и активизировать любой режим, поддерживаемый установленной видеокартой. Переключение режимов подробно рассматривается в главе 4.

Аппаратное ускорение

Основная причина, по которой DirectDraw обеспечивает оптимальное быстродействие, состоит в том, что во всех возможных случаях применяется аппаратное ускорение. Это означает, что видеокарта выполняет некоторые операции с помощью встроенных в нее аппаратных средств. Аппаратное ускорение обладает двумя основными преимуществами. Во-первых, в нем используются средства, спроектированные специально для ускорения графических операций. Тем самым обеспечивается максимальная скорость выполнения всех действий. Во-вторых, аппаратное ускорение освобождает процессор компьютера от необходимости выполнения этих операций, благодаря чему процессор может заняться другими задачами.

Поверхности

Поверхностью (surface) в DirectDraw называется прямоугольная область памяти, обычно содержащая графические данные. Блок памяти, изображающий поверхность, может находиться как в системной, так и в видеопамяти. Хранение поверхностей в видеопамяти обычно повышает скорость работы программы, поскольку большинство видеокарт не может обращаться к системной памяти напрямую.


Поверхности делятся на несколько типов. Простейшими являются внеэкранные (off-screen) поверхности. Внеэкранная поверхность может находиться как в видеопамяти, так и в системной памяти, но не отображается на экране. Такие поверхности обычно используются для хранения спрайтов и фоновых изображений.

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

Первичные поверхности часто бывают составными (complex), или, что то же самое, переключаемыми (flippable). Переключаемая поверхность может участвовать в переключении страниц — операции, при которой содержимое всей поверхности мгновенно отображается на экране с помощью специальных аппаратных средств. Переключение страниц используется во многих графических программах как с поддержкой DirectDraw, так и без, поскольку оно обеспечивает очень гладкую анимацию и устраняет мерцание. Переключаемая первичная поверхность на самом деле состоит из двух поверхностей, одна из которых отображается на экране, а другая — нет. Невидимая поверхность называется вторичным буфером (back buffer). При переключении страниц поверхности меняются местами: та, которая была вторичным буфером, отображается на экране, а та, что ранее отображалась, превращается во вторичный буфер.

Как внеэкранные, так и первичные поверхности делятся на две разновидности: палитровые (palettized) и беспалитровые (non-palettized). Палитровая поверхность вместо конкретных значений цветов содержит индексы в цветовой таблице, которая называется палитрой. В DirectDraw палитровыми являются только 8-битные поверхности. Поверхности с глубиной пикселей, равной 16, 24 и 32 битам, являются беспалитровыми. Вместо индексов в них хранятся фактические значения цветов.

Поскольку в каждом пикселе беспалитровой поверхности находятся реальные цветовые данные, необходимо знать, в каком формате хранятся отдельные пиксели поверхностей. Формат пикселя описывает способ хранения красной, зеленой и синей (RGB) составляющих. Он зависит от глубины пикселей, видеорежима и аппаратной архитектуры. Форматы пикселей подробно рассматриваются в главе 5.

Блиттинг

На жаргоне, принятом в компьютерной графике, «блиттингом» называется операция копирования. Примером типичного блиттинга служит копирование внеэкранной поверхности во вторичный буфер. Если аппаратное ускорение невозможно, DirectDraw эмулирует блиттинг на программном уровне. Такая эмуляция справляется

Графика для Windows средствами DirectDraw (2 стр.)

Программные требования

Для работы с книгой необходимо иметь Windows NT 4.0 или Windows 95. Кроме того, потребуется Visual C++ 5.0 или более поздней версии.

Вам также понадобится собственно DirectX версии 3a или выше (желательно DirectX 5). Учтите, что DirectX распространяется в двух видах: в runtime-варианте и в SDK. Runtime-вариант часто устанавливается программами, использующими DirectX, он также встроен в операционную систему Windows NT 4.0. На CD-ROM этой книги содержатся runtime-компоненты DirectX 5. С другой стороны, пакет DirectX SDK необходим для компиляции программ, написанных для DirectX. Он отсутствует на CD-ROM этой книги, однако его можно бесплатно скачать по адресу: www.microsoft.com/msdownload.

Аппаратные требования

Вам потребуется компьютер с процессором Pentium и выше. Под Windows NT необходимо иметь 32 Мбайт RAM, а под Windows 95 — не менее 16 Мбайт. Общий принцип остается прежним — чем больше, тем лучше. Также потребуется дисковод CD-ROM.

Наконец, понадобится видеокарта, поддерживаемая библиотекой DirectDraw (на данный момент DirectDraw поддерживают практически все современные видеокарты).

Пора заняться делом. Начнем с краткого курса DirectDraw.

Глава 1. Краткий курс DirectDraw

Полностью рассмотреть в одной главе всю библиотеку DirectDraw было бы нереально. В конце концов, даже о простейших аспектах DirectDraw написаны целые книги. DirectDraw представляет собой мощный и гибкий API, с помощью которого можно создать практически любое графическое приложение Windows. Именно гибкость существенно усложняет любые описания. Следовательно, было бы глупо пытаться рассмотреть все, от начала до конца, в одной главе.

И все же я решил попробовать.

Позвольте мне для начала рассказать о том, чего в этой главе не будет. Несомненно, вам уже приходилось слышать о DirectDraw. Наверняка вы видели демонстрационные программы и игры, написанные на базе этой библиотеки. Я избавлю вас от длинной тирады о светлом будущем графики в Windows. Хорошо написанное приложение DirectDraw говорит само за себя, поэтому мы обойдемся без охов и ахов.

Кроме того, я пропускаю многословные рассуждения о HAL (Hardware Abstraction Layer, прослойка абстрактной аппаратуры), HEL (Hardware Emulation Layer, прослойка эмуляции аппаратуры) и все кошмарные диаграммы, которые встречаются в справочных файлах SDK и некоторых книгах по DirectDraw. Вы читаете эту книгу, чтобы освоить программирование для DirectDraw, а не потому, что собираетесь писать драйверы устройств DirectDraw или изучать тонкости внутреннего устройства библиотеки.

В этой главе мы поговорим о практическом применении DirectDraw с точки зрения программиста. Прежде всего мы разберемся с тем, что же такое DirectDraw, и перейдем к обсуждению DirectDraw API. После этого будут рассмотрены некоторые практические вопросы, несомненно представляющие интерес при программировании для DirectDraw.

Что такое DirectDraw?

Весьма интересное определение DirectDraw можно найти у одного из его самых яростных противников — FastGraph. Графический пакет FastGraph появился уже довольно давно. В настоящее время существует версия FastGraph, которая поддерживает DirectDraw, но скрывает DirectDraw API за своим собственным нестандартным API. Тед и Диана Грубер (Ted and Diana Gruber), создатели и поставщики FastGraph, разместили на своем Web-узле файл, в котором доказывается, что FastGraph лучше DirectDraw.

В числе прочих доводов Груберы заявляют, что DirectDraw представляет собой «просто механизм блиттинга». Такая формулировка оказывается довольно точной, но чрезмерно упрощенной. Правильнее было бы сказать, что DirectDraw — аппаратно-независимый механизм блиттинга, наделенный некоторыми возможностями программной эмуляции. Главная задача DirectDraw как раз и заключается в том, чтобы по возможности быстро и надежно копировать графические изображения в память видеоустройств (блиттинг).

DirectDraw можно рассматривать и с другой точки зрения — как менеджер видеопамяти. DirectDraw распределяет блоки памяти и следит за состоянием каждого блока. Программы могут по своему усмотрению создавать, копировать, изменять и уничтожать такие блоки, причем конкретные подробности этих операций остаются скрытыми от программиста. Такое описание тоже оказывается излишне упрощенным. Во-первых, DirectDraw может использовать не только видеопамять, но и обычную память (RAM). Кроме того, при проектировании менеджеров памяти основное внимание обычно уделяется надежности, а не быстродействию. При проектировании же DirectDraw главной целью было именно быстродействие.

С технической точки зрения DirectDraw представляет собой переносимый API в сочетании с набором драйверов устройств. В своей работе DirectDraw полностью обходит традиционный графический механизм Windows (интерфейс графических устройств, GDI). GDI завоевал дурную славу своим низким быстродействием, поэтому независимость от него крайне важна для достижения оптимальной скорости.

Термины и концепции

Приняв к сведению все эти описания DirectDraw, давайте познакомимся с некоторыми терминами и концепциями, составляющими неотъемлемую часть используемого жаргона. Мы начнем с простейших, но основных понятий, которые относятся к графике вообще, а затем перейдем к специфике DirectDraw.

Видеорежимом называется набор параметров, поддерживаемый аппаратурой видеокарты (видеоадаптера) и позволяющий организовать вывод графического изображения. Самым известным атрибутом видеорежима является разрешение экрана. По умолчанию в Windows используется видеорежим с разрешением 640×480. Это означает, что на экране выводится 640 пикселей по горизонтали и 480 пикселей по вертикали. Также часто встречаются видеорежимы с разрешением 800×600 и 1024×768. Некоторые видеокарты поддерживают так называемые режимы ModeX. Типичный режим ModeX имеет разрешение 320×200.

Видеорежимы также различаются по глубине пикселей (pixel depth). Этот параметр определяет количество различных значений, принимаемых отдельным пикселем, и, следовательно, количество отображаемых цветов. Например, в видеорежиме с глубиной пикселей в 8 бит каждый пиксель может иметь один из 256 различных цветов. В режимах с 16-битной глубиной пикселей поддерживается отображение до 65536 цветов. Глубина пикселей обычно равна 8, 16, 24 или 32 битам.

Видеорежимы реализуются специальным устройством, установленным на компьютере, — видеокартой. На видеокарте устанавливается отдельная память, не входящая в основную память компьютера. Память, установленную на видеокарте, мы будем называть видеопамятью, а обычную память (RAM) — системной памятью. Объем памяти, необходимой для поддержки определенного видеорежима, определяется разрешением и глубиной пикселей в этом режиме. Например, для видеорежима 640×480×8 (640×480 пикселей, каждый из которых имеет глубину в 8 бит) требуется 307300 байт. Видеорежим 1024×768×16 требует 1572864 байт. Для поддержки видеорежимов используется видеопамять. Следовательно, режимы, поддерживаемые конкретной видеокартой, ограничиваются объемом установленной видеопамяти. Скажем, режим 1024×768×16 не поддерживается видеокартами с 1 Мбайт памяти, потому что для него такой объем памяти недостаточен.

Одна из ключевых возможностей DirectDraw — переключение видеорежимов. Она позволяет приложению DirectDraw обнаружить и активизировать любой режим, поддерживаемый установленной видеокартой. Переключение режимов подробно рассматривается в главе 4.

Основная причина, по которой DirectDraw обеспечивает оптимальное быстродействие, состоит в том, что во всех возможных случаях применяется аппаратное ускорение. Это означает, что видеокарта выполняет некоторые операции с помощью встроенных в нее аппаратных средств. Аппаратное ускорение обладает двумя основными преимуществами. Во-первых, в нем используются средства, спроектированные специально для ускорения графических операций. Тем самым обеспечивается максимальная скорость выполнения всех действий. Во-вторых, аппаратное ускорение освобождает процессор компьютера от необходимости выполнения этих операций, благодаря чему процессор может заняться другими задачами.

Графика для Windows средствами DirectDraw

НАСТРОЙКИ.

СОДЕРЖАНИЕ.

СОДЕРЖАНИЕ

«Графика для Windows средствами DirectDraw»

Посвящается Стэнли и Велме Коппок (моим дедушке и бабушке по материнской линии), а также Дж. Д. и Марии Трухильо (дедушке и бабушке по отцовской линии). Их общество и поддержка радовали меня в детстве и продолжают радовать сейчас.

Программисты (особенно начинающие) любят задавать вопросы типа: «Скажи, на чем ты пишешь…?» Когда-то этот вопрос выглядел вполне логично.

Компиляторы, отладчики, серверы, системы управления базами данных и все остальное только-только выходило из каменного века. Программные инструменты разительно отличались друг от друга по качеству и возможностям. Стоило сделать ставку на неудачный инструментарий, и работа становилась излишне тяжкой, а качество результата — низким.

Сегодня стал актуальным другой вопрос: «А чего стоишь ты сам?» Благодаря непрерывной конкуренции современные средства разработчика стали невероятно мощными и качественными, так что среднему программисту вряд ли удастся выжать из них все возможное. Скорее всего, вы спасуете намного раньше, чем ваш инструментарий — если только не узнаете о нем абсолютно все и не доведете свое мастерство программиста до подлинного совершенства.

Книги этой серии предназначены для углубленного изучения программных инструментов. В них рассматриваются нетривиальные возможности, которые невозможно описать в простейшем учебнике. Полноценные проекты заставляют читателя мыслить на уровне эксперта — напрягать серое вещество, лежащее в основе всего, что мы называем «мастерством».

Конечно, это не единственный путь — например, можно добросовестно набивать шишки обо все острые углы новых технологий и наобум пробовать все подряд, пока что-нибудь не заработает. А можно воспользоваться опытом наших авторов, которые уже прошли стадию обучения и попутно сделали кое-какие заметки на память. Мы тщательно отобрали темы, авторов и методику изложения, чтобы читатель не путался в ненужных вступлениях или редких технологиях, которые ему все равно не понадобятся.

Наша главная цель — поднять ваше мастерство настолько, насколько вы сами захотите. Классные инструменты у вас уже есть, осталось лишь стать классным программистом.

Засидевшись допоздна над своей предыдущей книгой, «Cutting-Edge Direct3D Programming», я решил ложиться спать. Оказалось, что та же самая мысль пришла в голову здоровенному пауку-каракурту. Что еще хуже, для этого нами была выбрана одна и та же кровать. Мы мирно улеглись, не подозревая о присутствии друг друга (во всяком случае, я ничего не подозревал).

До того мне приходилось слышать о каракуртах и даже видеть их время от времени. Бесспорно, они пользуются дурной славой. Я полагал, что после укуса каракурта следуют пять или десять минут невыносимой боли, а затем неизбежно наступает смерть. Оказалось, я ошибался в обоих отношениях. Сам по себе укус проходит совершенно безболезненно, но если его не лечить, боль продолжается до 48 часов. Тем не менее укус каракурта (даже без лечения) редко бывает смертельным.

И мне, и пауку пришлось пожалеть о встрече. Пауку — потому что он был жестоко раздавлен своей разгневанной и удивленной жертвой. Мне — потому что у врача я оказался лишь через восемь часов после укуса (а серьезные мышечные спазмы начинаются через 2–4 часа). После нескольких посещений местной амбулатории проблема была решена. Этой ночью я так и не спал, и к тому же в течение восьми часов мучался от жуткой боли. В довершение всего перед вводом противоядия меня накачали валиумом. Разумеется, о работе не могло быть и речи.

При первой возможности я позвонил своему редактору, Скотту Палмеру (Scott Palmer). Заплетающимся языком я рассказал, что немного задержусь с очередной главой, потому что меня укусил каракурт. Скотт проявил полное понимание, и мы перенесли срок сдачи материала.

Через несколько месяцев Скотт прислал мне первую главу своей новой книги. Книга была посвящена написанию технической литературы, а в главе говорилось о том, что ему пришлось узнать, будучи то автором, то редактором. В самом конце был приведен список отговорок, которыми авторы объясняли свои задержки. Представьте, он начинался с укуса каракурта!

Скотт заверил меня, что он никогда не сомневался в моей искренности, а в список включил сразу все оправдания, независимо от того, поверил он или нет. Тем не менее полагаю, его позиция вполне ясна.

Редактором этой книги была Мишель Страуп. Она берется за дело довольно жестко, так что мне повезло, что при написании этой книги дело обошлось без медицинского вмешательства — не то, пожалуй, пришлось бы посылать ей факсом справку от врача.

Но давайте поговорим серьезно. Издатели считают, что авторы отвечают за качество материала и соблюдение графика. В свою очередь, по мнению автора, издатели отвечают за маркетинг и распространение книг. Иногда так и получается, а иногда обе стороны разочаровываются друг в друге. Но в любом случае читатель по праву надеется получить полезную, надежную и содержательную книгу.

Другими словами, Coriolis отвечает за распространение и продажу книги, однако за содержащийся в ней материал отвечаю я. Следовательно, если у вас возникнут какие-либо вопросы по поводу программ или CD-ROM, не стесняйтесь и пишите мне. Некоторые читатели обращаются в Coriolis, но издательство все равно просто пересылает почту мне. Если вы захотите обратиться ко мне, обязательно укажите, о какой книге идет речь, и постарайтесь сделать свои вопросы и замечания по возможности конкретными. Со мной можно связаться по адресу mailto:stan@rezio.com.

Кроме того, некоторые вопросы встречаются особенно часто. Я собираюсь создать и вести список ЧаВО (часто задаваемых вопросов) на Web-узле этой книги (www.rezio.com/wgp). Здесь вы найдете ответы на некоторые вопросы, а также исправления ошибок, обновления и, возможно — даже новые демонстрационные программы.

Для чего написана эта книга

В той отрасли, где мы работаем, библиотека DirectDraw появилась довольно давно. Во всяком случае, за это время она успела доказать свои возможности, и о ней было написано несколько книг. Как обычно, эти книги отличаются по своему качеству. Однако в основном это были добротные учебники, которые (как и многие книги о компьютерах) были написаны за три месяца авторами, изучавшими предмет по ходу дела. В результате большинство этих книг содержит лишь подготовительный материал. Теперь, когда библиотека DirectDraw подросла и обрела свою репутацию (во всяком случае, она старше других компонентов DirectX), настало время уйти от основ и познакомиться с ее некоторыми нетривиальными возможностями.

Эта книга начинается с того, на чем другие книги обычно заканчивались. Мы поговорим об основах DirectDraw, но лишь в общих чертах. Читатель — опытный программист, но незнакомый с DirectDraw — сможет с ходу войти в курс дела. Затем мы перейдем к другим темам, столь же интересным, сколь и полезным.

Цель этой книги — научить вас работать с DirectDraw, а не предоставить некоторую «структурную основу» или нестандартный API, который бы выполнял за вас всю работу. Демонстрационные программы написаны на C++ и используют MFC, но совсем не для того, чтобы скрыть все технические подробности. С++ и MFC — превосходные инструменты, потому что с их помощью любое приложение можно написать несколькими разными способами. Примеры для этой книги были написаны так, чтобы при этом получались структурированные и удобные для чтения проекты, которые наглядно показывают, что и почему происходит в программе.

Помимо DirectDraw, во многих примерах используется библиотека DirectInput. Строго говоря, при программировании графики для Windows можно обойтись и без DirectInput, но ей все же стоит воспользоваться. Она работает быстрее традиционных средств ввода Windows и к тому же входит в DirectX, так что для работы с ней не потребуется никаких дополнительных SDK.

Требования к читателю

Эта книга научит вас почти всему, что можно узнать о DirectDraw. Тем не менее она не учит C, C++, MFC или работе с Developer Studio пакетов семейства Visual — предполагается, что вы уже знакомы с этими темами. С другой стороны, от вас не требуется никаких выдающихся познаний. Например, мы будем использовать MFC, но лишь в объеме, необходимом для написания наших приложений. Следовательно, чтобы читать эту книгу, вовсе не обязательно быть экспертом в MFC.

DDS (Microsoft DirectDraw Surface)

Microsoft DirectDraw Surface (DDS) is a standard format used to store image data in MicrosoftR DirectX.

Microsoft DirectDraw Surface (DDS) is used to store surface and texture data. With textures whose side size is equal to degrees of two, it is possible to save mipmap levels.

This format can store information in compressed and uncompressed pixel format. Use it to store compressed data in DXTn format.

Online image converter to DDS can save image data with the following pixel formats:

R8G8B8: (24 bits per pixel, R:8, G:8, B:8)
R5G6B5: (16 bits per pixel, R:5, G:6, B:5)
A8R8G8B8: (32 bits per pixel, A:8, R:8, G:8, B:8)
A8B8G8R8: (32 bits per pixel, A:8, B:8, G:8, R:8)
X8R8G8B8: (32 bits per pixel, A:x, R:8, G:8, B:8)
X8B8G8R8: (32 bits per pixel, A:x, B:8, G:8, R:8)
A1R5G5B5: (16 bits per pixel, A:1, R:5, G:5, B:5)
X1R5G5B5: (16 bits per pixel, A:x, R:5, G:5, B:5)
L8: (8 bits per pixel, luminance:8)
A8L8: (16 bits per pixel, A:8, L:8)
DXT1: (compressed, 1-bit alpha)
DXT2: (compressed, 4-bit premultiplied alpha)
DXT3: (compressed, 4-bit nonpremultiplied alpha)
DXT4: (compressed, interpolated premultiplied alpha)
DXT5: (compressed, interpolated nonpremultiplied alpha)

To use DDS format successfully, you should note these features:

When saving to DDS with mipmap levels option, the size of the image you are saving should be equal to a degree of two (128, 512, 1024 etc.).

If image size doesn’t match resize the image to match the needed size.

Surface у DirectDraw

Advanced: Тема повышенной сложности или важная.

Вот решил новую игру сделать. Сначало надо сделать движок. Начал с того, что подключил DirectDraw7 и все прочее и т.д. Но вот когда дошло дело до блиттеров. Хочу передать заднему буфферу спрайт, но работает только тогда когда я растягиваю изображение на весь екран, если я этого не делаю оно либо само растягивается либо вообще ничего не показывает. Что делать? Вот код:

if(FAILED(c->lpdd->SetCooperativeLevel(c->hwnd,DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX |
DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
myERROR(«ERROR in CrMainWnd (Create main window)»,»Can’t set the cooperative LEVEL(DDraw). «);
c->lpdd->SetDisplayMode(800,600,32,0,0);
memset((void*)&c->ddsdesk,0,sizeof(c->ddsdesk));
c->ddsdesk.dwSize = sizeof(DDSURFACEDESC2);
c->ddsdesk.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
c->ddsdesk.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
c->ddsdesk.dwBackBufferCount = 1;
if(FAILED(c->lpdd->CreateSurface(&c->ddsdesk,&c->lpddsprimary,NULL)))
myERROR(«ERROR in CrMainWnd (Create main window)»,»Can’t create DDraw Surface Primary 2. «);
c->ddsdesk.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
if(FAILED(c->lpddsprimary->GetAttachedSurface(&c->ddsdesk.ddsCaps,&c->lpddsback)))
myERROR(«ERROR in CrMainWnd (Create main window)»,»Can’t create DDraw Surface Back 2. «);
RECT rclipp[1] = <<0,0,800,600>>;
if(FAILED(c->lpdd->CreateClipper(0,&c->lpddclipper,NULL)))
myERROR(«ERROR in CrMainWnd (Create main window)»,»Can’t create DirectDraw7 Clipper. «);
c->lprgndata = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+sizeof(RECT));
memcpy((void*)c->lprgndata->Buffer,(void*)rclipp,sizeof(RECT));
c->lprgndata->rdh.dwSize = sizeof(RGNDATAHEADER);
c->lprgndata->rdh.iType = RDH_RECTANGLES;
c->lprgndata->rdh.nCount = 1;
c->lprgndata->rdh.nRgnSize = sizeof(RECT);
c->lprgndata->rdh.rcBound.left = 64000;
c->lprgndata->rdh.rcBound.top = 64000;
c->lprgndata->rdh.rcBound.right = -64000;
c->lprgndata->rdh.rcBound.bottom = -64000;
if(FAILED(c->lpddclipper->SetClipList(c->lprgndata,0)))
myERROR(«ERROR in CrMainWnd (Create main window)»,»Can’t set the Clipper list. «);
if(FAILED(c->lpddsback->SetClipper(c->lpddclipper)))
myERROR(«ERROR in CrMainWnd (Create main window)»,»Can’t set the clipper to DDraw Back Surface. «);
sprite sp;
sp.LoadSpriteFromImage(L»D:\\Linesoft\\pics\\pic8.bmp»,L»D:\\Linesoft\\pics\\pic8.bmp»,c);
RECT r,r2;
r.top = 0;
r.left = 0;
r.right = sp.pos.width-1;
r.bottom = sp.pos.height-1;
r2.top = 100;
r2.left = 100;
r2.bottom = 300+1;
r2.right = 370+1;
RECT rr[1] = <<20,20,100,100>>;
c->lpddsback->Blt(&r,sp.body,rr,(DDBLT_WAIT),NULL);
c->lpddsprimary->Flip(NULL,DDFLIP_WAIT);
//myERROR(«t»,»t»);
>
После выполнения этого кода изображение показивается на весь екран.

Глюк бил у клипперах. Вот здесь:
c->lprgndata->rdh.rcBound.left = 64000;
c->lprgndata->rdh.rcBound.top = 64000;
c->lprgndata->rdh.rcBound.right = -64000;
c->lprgndata->rdh.rcBound.bottom = -64000;

Zegalur
Хорошо бы код оформлять тегом, а то читать невозможно.

DirectX DirectDraw Surface Palette

LockedData Ddata — возвращает регион по 32 бита на пиксел ((
Как создать (или глобально работать с directDraw) палитровый surface (8бит на пиксел)
Облазил форумы, но ничего дельного..
пишу на шарпе.
Заранее спасибо

пример моего кода

10.07.2011, 00:13

Как получить элемент surface из xml документа
Как получить surfase из xml документа. Далее хочу присвоить string str = «surface»; Выкладывать.

Демонстрация примера DirectX 9 и DirectDraw
Разбираюсь с managed DirectX. Решил поделиться тем, что нашёл, может кому и пригодится. НО.

Directx 11: недоступны функции Ускорение DirectDraw, Direct3D, Ускорение текстур AGP
Здравствуйте. Вся проблема как я понял в том, что у меня не правильно работает Directx. Я никак не.

ActiveX, Tool Palette
всем привет. Читаю книгу Архангельского » Программирование в С++ builder». А там есть раздел.

Генерация Color Palette
Есть ли инструмент который генерирует все остальные цвета.

10.07.2011, 00:13

Окно Tool Palette
Привет всем. Может кто подскажет как создать окно похожее на окно Tool Palette или Project Manager.

Tool Palette — Инструктаж)
Подскажите как создать такие «компоненты» что выделены под номерами 1, 2 и 3, пажалуйста. А именно.

Delphi IDE palette components
Здравствуйте. Работаю с Delphi7. Решил перейти на 2007. Поставил, но никак не вижу палеты с.

DirectDraw Surface — DirectDraw Surface

Поверхности DirectDraw формат файла — контейнера (использует расширение файла DDS ), является Microsoft формат для хранения данных , сжатых с фирменной S3 Texture Compression (S3TC) алгоритм, который может быть распакованы в аппаратном обеспечении графических процессоров . Это делает формат полезный для хранения графических текстур и кубических карт окружающей среды в качестве файла данных , как сжатых и несжатого. Расширение файла для этого формата данных является».dds’.

содержание

история

Этот формат был введен с DirectX 7.0. В DirectX 8.0, была добавлена поддержка объемных текстур. С Direct3D 10 , формат файла был расширен , чтобы позволить массив текстур , которые будут включены, а также поддержка новых Direct3D 10.x и 11 текстурных форматов.

Илон Маск рекомендует:  Применение таблиц
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL