Первая анимация

Xakep, номер #045, стр. 045-063-2


После вызова метода Lock адрес памяти, где находятся данные поверхности, находится в свойстве lpSurface структуры, переданной в качестве второго параметра. Вот тут, наверно, нужно будет написать реальный пример, а потом разобрать его по косточкам.

Первый пример

Я написал небольшую процедуру PutPixel, которая будет выводить на экран один пиксель в видеопамять поверхности:

Procedure PutPixel(X, Y: Integer; R, G, B : Byte);

var

desc : TDDSURFACEDESC2;

Value:Word;

begin

ZeroMemory (@desc, SizeOf(desc)); //Обнуляю структуру

desc.dwSize := SizeOf(desc); //Заполняю размер

value:=B or (G shl 5) or (R shl 11); //Вычисляю цвет

FImageSurface.Lock (nil, desc, DDLOCK_WAIT, 0); //Блокировка

//Вывод точки

PWord(Integer(desc.lpSurface) + Y * desc.lPitch + X*2)^ := Value;

FImageSurface.Unlock (nil);//Разблокировка

end;

У этой процедуры всего пять параметров:

X - позиция по горизонтали, куда надо вывести точку;

Y - y позиция по вертикали, куда надо вывести точку;

R - значения красного цвета точки;

G - значения зеленого цвета точки;

B - значения голубого цвета точки.

Из параметров R, G и B мы будем составлять цвет точки.

Теперь перейдем к коду функции. Первым делом я обнуляю структуру desc и в поле dwSize заношу ее размер.

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

Цвет в DirectDraw

Если ты используешь разрешение в 8 бит (максимум, что можно отобразить, - 256 цветов, и то благодаря палитре), то никаких проблем. У тебя в памяти каждый байт - это указатель на цвет в палитре, т.е. картинка 8х8 будет выглядеть так:

125 002 015 121 146 166 004 112

225 255 125 125 003 168 112 036

125 082 015 021 146 166 004 112

225 255 125 125 003 168 112 036

225 255 125 125 003 168 112 036

125 082 015 021 146 166 004 112

225 255 125 125 003 168 112 036

125 082 015 021 146 166 004 112

Тут каждое число означает какой-то цвет. Если мы используем режим TrueColor, то в этом режиме каждые три рядом стоящих байта дают цвет. Это значит, что наша табличка должна расшириться в ширину в три раза. В этом случае каждые три байта будут давать цвет (RGB).

Ну а самое интересное происходит при 16-битном цвете, когда в два байта нужно засунуть три цвета. Как это сделать, если два байта - это 16 бит, а 16 на 3 не делится? Очень просто - в этом случае очень часто используется режим 5-6-5, где 5 бит под красный цвет, 6 бит под зеленый и 5 бит под голубой. Можно переключиться на режим 5-5-5, где всем цветам будет отдано одинаковое количество бит, но мы будем рассматривать 5-6-5. Так как 16-битный режим самый сложный, я решил использовать в своем примере именно его. Надеюсь, что с остальными проблем не будет.

Чтобы получить результирующий цвет и засунуть его в переменную Value (которая имеет тип WORD или два байта), мне нужно сдвинуть красный цвет на 11 бит влево, зеленый на 5 бит и синий прибавить как есть. Именно это и происходит в следующей строке кода:

Назад на стр. 045-063-1  Содержание  Вперед на стр. 045-063-3