Звезда сначала абсолютно прозрачна, но со временем становится плотнее. Цвета квадрата и звезды накладываются точно, образуя оттенки желтого, пока звезда не станет совершенно непрозрачной.
Вспомогательная переменная Alpha последовательно принимает значения от 0 до 255 и используется в функции рисования звезды, при задании цветовой составляющей вершин:
for i := 0 to High (VStar) do
VStar [i].Color := D3DCOLOR_ARGB(Alpha, 0, 255, 0) ;
Обратите внимание, что теперь для задания цвета вершины используется функция D3DCOLOR_ARGB, аргументом которой является четверка чисел. Первый аргумент - значение альфа-компонента.
При перерисовке кадра режим альфа-смешения устанавливается только на время работы функции рисования звезды из соображений оптимальности:
with FDSDDevice do begin
SetRenderState(D3DRS_ALPHABLENDENABLE, DWORD(True));
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
end;
hRet := DrawStar; if FAILED(hRet) then begin
Result := hRet;
Exit; end; FDSDDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, DWORD (False));
Для режима регулируемой прозрачности значение степени прозрачности источника определяется текущим значением альфа-составляющей цвета вершин. Режиму соответствует константа D3DBLEND_SRCALPHA. В данном режиме каждый чистый цвет источника имеет коэффициент прозрачности, равный значению альфа-составляющей. Для режима смешения цветов режим приемника задается константой DSDBLEND^NVSRCALPHA так, что суммарно получается единица - итоговый пиксел совершенно непрозрачный:
* D3DBLEND__SRCALPHA: коэффициент смешения (Aj, AS, As, AS); D3DBLEND_INVSRCALPHA: Коэффициент смешения (1-Aj, 1~ AS, 1-AS, 1~AS).
He путайте с весом цвета, речь идет о прозрачности каждого цветового компонента.
Совсем необязательно, чтобы все вершины, образующие примитив, имели одинаковое значение альфа-компонента. Варьируя альфа-составляющую, можно добиваться эффекта градиентной прозрачности примитива. В качестве примера использования такого эффекта я приготовил проект каталога Ех03- полноэкранное приложение, в котором при каждом щелчке кнопки мыши на экране расплываются красивые полупрозрачные пятна.
Для манипуляций с пятнами использую концепцию ООП:
type
TRGB = packed record // Запись тройки цветов
R, G, В : Byte;
end;
TDrip = class // Класс отдельного пятна
PosX, PosY : Integer; // Координаты на экране
Ring_Color : TRGB; // Цвет пятна
Ring_Radius : Integer; // Текущий радиус пятна
end;
const
Level =36; // Уровень разбиения круга
Max Drips = 120; // Максимум присутствия пятен в окне
Max_Ring_Radius = 100.0; // Максимальный радиус пятна var
VCircle : Array [0..Level + 1] of TCUSTOMVERTEX; // Вершины круга
First_Drip, New_Drip : Integer; // Счетчики пятен
Drips : Array [0..Max_Drips - 1] of TDrip; // Массив пятен
При каждом нажатии кнопки мыши создается новое пятно. Координатами его центра выступают текущие координаты курсора:
procedure Create_Drip(const inX, inY : Integer; const R, G, В : Byte);
begin
// Создание нового пятна
Drips [New_Drip] := TDrip.Create;
with Drips[New_Drip] do begin
Ring_Color.R := R;
Ring_Color.G := G;
Ring_Color.B := B;
Ring_Radius := 0;
PosX := inX;
PosY := inY;
end;
// Увеличение счетчиков
New_Drip := (New_Drip + 1) mod Max_Drips;
// Достигнут предел по количеству пятен на экране
if New_Drip = First_Drip
then First_Drip := (First_Drip + 1) mod Max_Drips;
end;
procedure TfrmD3D.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Create_Drip(X,Y,random(lSO)+105,random(150)+105, random(150)+105);
end;
Вес чистых цветов выбирается из некоторого диапазона. При градиентной прозрачности примитивов для больших треугольников или при чересчур низком весе цветов образуются полоски, портящие картинку (возможно, при использовании не каждой видеокарты). Ограничение для размеров кругов установлено также с целью предотвращения появления таких узоров.
Для рисования каждого пятна вызывается функция Drawcircle, круг рисуется группой связанных треугольников:
function TfrmD3D.DrawCircle (const inX, inY, inRadius : Integer;
const Ring_Color : TRGB) : HRESULT;
const
Step = 2 * Pi / Level;
var
pVertices : PByte;
hRet : HRESULT; i : Integer;
begin
// Первая точка - центр круга
with VCircle [0] do begin
X := inX;
Y := inY;
// Точка центра совершенно непрозрачна
Color := D3DCOLOR_ARGB(255, Ring_Color.R, Ring_Color.G, Ring_Color.B);
end;
// Точки края круга абсолютно прозрачны
for i := 1 to Level + 1 do
with VCircle [i] do begin
X := VCircle [0].X + cos (i * Step) * inRadius;
Y := VCircle [0].Y + sin (i * Step) * inRadius;
Color := D3DCOLOR_ARGB(0, Ring_Color.R, Ring_Color.G, Ring_Color.B);
end;
hRet := FD3DVB.Lock(0, SizeOf(VCircle), pVertices, 0) ;
if Failed (hRet) then begin
Result := hRet;
Exit;
end;
Move (VCircle, pVerticesA, SizeOf(VCircle));
hRet := FD3DVB.Unlock;
if Failed (hRet) then begin
Result := hRet;
Exit ;
end;
Result := FD3DDevice.DrawPrimitive(D3DPTJTRIANGLEFAN, 0, Level);
end;
При перерисовке кадра отображается круг для каждого существующего пятна:
Читать дальше
Конец ознакомительного отрывка
Купить книгу