Гамма-контроль используется для обеспечения цветовых переходов в непалитровых режимах и управляет яркостью изображения. Примером создания fade-эффекта в 32-битном режиме является проект каталога Ех03. Здесь появилась переменная специального типа, связанного с гамма-контролем:
g_pGarnmaControl: IDIRECTDRAWGAMMACONTROL;
Поскольку не каждая видеокарта поддерживает эту возможность, необходимо определиться, возможна ли корректная работа приложения:
function TfrmDD.HasGammaSupport : BOOL;
var
ddcaps : TDDCAPS; // Структура описания возможностей драйвера
begin
ZeroMemory(@ddcaps, sizeof(ddcaps));
ddcaps.dwSize := sizeof(ddcaps);
// Получаем список возможностей
g_pDisplay.GetDirectDraw.GetCaps(@ddcaps, nil);
// Поддерживается ли гамма-контроль аппаратно?
if(ddcaps.dwCaps2 and DDCAPS2_PRIMARYGAMMA) <> 0
then Result := TRUE
else Result := FALSE;
end;
В этом примере при отсутствии аппаратной поддержки приложение завершает работу. В принципе этого можно не делать. Не должно возникать исключений в работе приложений при отсутствии аппаратной поддержки такой возможности. Просто на экране по ходу работы не будет заметно никаких изменений.
В примере на экране рисуются три красивые полосы, образованные плавным переходом черного цвета в каждый из тройки чистых цветов. Как это осуществляется, разберите самостоятельно. Чтобы полосы равномерно заполняли экран при любых установках, необходимо получить данные о формате пиксела, для чего предназначен метод поверхности (объекта типа
CSurface) GetBitMasklnfo.
Проект, располагающийся в каталоге Ех04, отличается от предыдущего тем, что вместо полос на экран выводится система мечущихся логотипов.
Для задания текущей яркости служит целочисленная переменная:
g_lGammaRamp : Longlnt = 256;
Работа по осуществлению гамма-контроля очень похожа на работу с палитрой:
function TfrmDD.UpdateGammaRamp : HRESULT;
var
hr : HRESULT;
ddgr : TDDGAMMARAMP; // Набор значений яркости чистого цвета dwGamma : WORD; iColor : Integer;
begin
ZeroMemory(@ddgr, sizeof (ddgr));
// Получаем текущие значения яркостей
hr := g_pGammaControl.GetGanimaRamp(0, ddgr);
if(FAILED(hr)) then begin
Result := hr;
Exit
end;
dwGamma := 0;
// Последовательно наращиваем яркость цветовых составляющих
for iColor := 0 to 255 do begin
ddgr.red[iColor] := dwGamma;
ddgr.green[iColor] := dwGamma;
ddgr.blue[iColor] := dwGamma;
dwGamma := dwGamma + g_lGammaRamp;
end;
// Устанавливаем текущую "палитру"
hr := g_pGainmaControl. SetGammaRamp (0, ddgr) ;
if(FAILED(hr)) then begin
Result := hr;
Exit
end;
Result := S_OK;
end;
Привожу еще один вариант использования модуля DDuti8 (проект каталога Ех05) - иллюстрацию непосредственной работы с пикселами поверхности. Здесь таким способом подготавливаются поверхности спрайтов. Пример рассчитан на работу в 16-битном режиме и использует указатели PWORD. Принципиально ничего нового в коде не появилось. Библиотека DDUtil8 ничего не изменила в этой части, поэтому не стану подробно разбирать код. Только обращаю ваше внимание на то, что этот пример, подобно предыдущему, корректно работает с любым форматом пиксела, поскольку опирается на присутствующие битовые маски.
Надеюсь, такого беглого знакомства с библиотекой DDUtil8 для вас оказалось достаточным для того, чтобы получить представление о ней.
Вернемся к обычному для этой книги подходу, лишенному объектной ориентированности. Рассмотрим следующий пример - проект, располагающийся в каталоге Ех06. Пример можно отнести к разряду классических, он является моей интерпретацией программы stretch.cpp из DirectX 6.0 SDK. Это оконное приложение, на экране выводится образ вращающегося в пространстве тора (рис. 4.1).
Мультфильм намеренно подготовлен таким образом, чтобы создать у зрителя иллюзию трехмерной графики. На самом деле последовательно выводятся отдельные кадры с изображением различных фаз поворота тора.
Размер отдельного кадра 64x64 пиксела. Все кадры записаны в одно растровое изображение donut.bmp в шесть рядов по десять кадров. Растр загружается на поверхность FDDSImage. При перерисовке экрана на первичную поверхность выводится прямоугольник очередной фазы поворота тора:
function TfrmDD.UpdateFrame : HRESULT;
var
rcRect : TRECT;
begin
Inc (Frames);
ThisTickCount := GetTickCount;
if ThisTickCount - LastTickCount > TimeDelay then begin
FPS : = PChar ('FPS = ' + Format('%6.2f,
[Frames * 1000 / (ThisTickCount - LastTickCount)])); Caption := FPS; Frames := 0;
// Наращиваем текущий кадр; всего 60 кадров
CurrentFrame := (CurrentFrame + 1) mod 61;
// Прямоугольник очередного кадра; "shl 6" равносильно " * 64" SetRect (rcRect,
(CurrentFrame mod 10) shl 6,
(CurrentFrame div 10) shl 6,
(CurrentFrame mod 10 + 1) shl 6,
(CurrentFrame div 10 + 1) shl 6);
Читать дальше
Конец ознакомительного отрывка
Купить книгу