Тема: Texture Generator
Этот пример генерирует случайным образом изображение.
Рисуется во весь экран, выход по нажатию клавиши.
Изначальный исходный код под Windows я взял с этого французского сайта
И адаптировал его под KolibriOS.
Исходный код:
program TextureGenerator;
uses
KolibriOS;
const
WS_NO_DRAW = $1000000;
type
TRGBQuad = packed record
Blue, Green, Red, Alfa: Byte;
end;
PLongA = ^TLongA;
TLongA = array [0..0] of LongWord;
PByteA = ^TByteA;
TByteA = array [Word] of Byte;
PRGBQuadA = ^TRGBQuadA;
TRGBQuadA = array [Word] of TRGBQuad;
const
B: Integer = $100;
BM: Integer = $FF;
N: Integer = $1000;
Ni: Integer = $400000;
NM: Integer = $FFF;
NP: Integer = 12;
B2: Integer = $202; // B + B + 2;
var
P: array [0..$202] of Integer;
G1: array [0..$202] of Double;
G2: array [0..$202, 0..1] of Double;
G2i: array [0..$202, 0..1] of Integer;
G3: array [0..$202, 0..2] of Double;
G3i: array [0..$202, 0..2] of Integer;
bmg: PLongA;
Map, Map1: PLongA;
HighMap: LongInt;
MapSizeX: LongWord;
MapSizeY: LongWord;
WndHeight, WndWidth: LongWord;
function Random: Extended;
begin
Random := LongWord(System.Random($FFFFFFFF)) / $FFFFFFFF;
end;
function Round(Value: Extended): Int64;
asm
FLD Value
SUB ESP, 8
FISTP qword ptr [ESP]
FWAIT
POP EAX
POP EDX
end;
function Trunc(Value: Extended): Int64;
asm
FLD Value
SUB ESP, 12
FNSTCW word ptr [ESP]
FNSTCW word ptr [ESP + 2]
FWAIT
OR word ptr [ESP + 2], $0F00
FLDCW word ptr [ESP + 2]
FISTP qword ptr [ESP + 4]
FWAIT
FLDCW word ptr [ESP]
POP ECX
POP EAX
POP EDX
end;
function Min(A, B: Integer): Integer; overload;
begin
if A < B then
Min := A
else
Min := B;
end;
function Min(A, B: Extended): Extended; overload;
begin
if A < B then
Min := A
else
Min := B;
end;
procedure InitNoise;
var
I, J, T: Integer;
len: Double;
begin
Randomize;
for i := 0 to B - 1 do
begin
P[i] := i;
G1[i] := (Trunc(Random * 2 * B) - B) / B;
G2[i, 0] := (Trunc(Random * 2 * B) - B) / B;
G2[i, 1] := (Trunc(Random * 2 * B) - B) / B;
len := Sqrt(G2[i, 0] * G2[i, 0] + G2[i, 1] * G2[i, 1]);
if len > 1E-5 then
begin
G2[i, 0] := G2[i, 0] / len;
G2[i, 1] := G2[i, 1] / len;
end;
G2i[i, 0] := Trunc(G2[i, 0] * 1024);
G2i[i, 1] := Trunc(G2[i, 1] * 1024);
G3[i, 0] := (Trunc(Random * 2 * B) - B) / B;
G3[i, 1] := (Trunc(Random * 2 * B) - B) / B;
G3[i, 2] := (Trunc(Random * 2 * B) - B) / B;
len := Sqrt(G3[i, 0] * G3[i, 0] + G3[i, 1] * G3[i, 1] + G3[i, 2] * G3[i, 2]);
if len > 1E-5 then
begin
G3[i, 0] := G3[i, 0] / len;
G3[i, 1] := G3[i, 1] / len;
G3[i, 2] := G3[i, 2] / len;
end;
G3i[i, 0] := Trunc(G3[i, 0] * 1024);
G3i[i, 1] := Trunc(G3[i, 1] * 1024);
G3i[i, 2] := Trunc(G3[i, 2] * 1024);
end;
for i := 0 to B - 1 do
begin
j := Trunc(Random * B);
T := P[i];
P[i] := P[j];
P[j] := T;
end;
for i := 0 to B + 1 do
begin
P[B + i] := P[i];
G1[B + i] := G1[i];
G2[B + i][0] := G2[i][0];
G2[B + i][1] := G2[i][1];
G2i[B + i][0] := G2i[i][0];
G2i[B + i][1] := G2i[i][1];
G3[B + i][0] := G3[i][0];
G3[B + i][1] := G3[i][1];
G3[B + i][2] := G3[i][2];
G3i[B + i][0] := G3i[i][0];
G3i[B + i][1] := G3i[i][1];
G3i[B + i][2] := G3i[i][2];
end;
end;
function Noise2Di(const x, y: Integer): Integer;
var
bx0, bx1, by0, by1: Integer;
b00, b10, b01, b11: Integer;
rx0, rx1, ry0, ry1: Integer;
sx, sy, t, a, b, u, v: Integer;
i, j: Integer;
r: Integer;
begin
t := x + $40000000;
bx0 := (t shr 10) and $FF;
bx1 := (bx0 + 1) and $FF;
i := P[bx0];
rx0 := t and 1023;
rx1 := rx0 - 1024;
t := y + $40000000;
by0 := (t shr 10) and $FF;
by1 := (by0 + 1) and $FF;
j := P[bx1];
ry0 := t and 1023;
ry1 := ry0 - 1024;
b00 := P[i + by0];
b10 := P[j + by0];
b01 := P[i + by1];
b11 := P[j + by1];
sx := (rx0 * rx0 * (3072 - 2 * rx0)) shr 20;
sy := (ry0 * ry0 * (3072 - 2 * ry0)) shr 20;
u := (rx0 * G2i[b00][0] + ry0 * G2i[b00][1]);
v := (rx1 * G2i[b10][0] + ry0 * G2i[b10][1]);
a := (u shl 10) + sx * (v - u);
asm
SAR a, 20
end;
u := (rx0 * G2i[b01][0] + ry1 * G2i[b01][1]);
v := (rx1 * G2i[b11][0] + ry1 * G2i[b11][1]);
b := (u shl 10) + sx * (v - u);
asm
SAR b, 20
end;
r := a shl 10 + sy * (b - a);
asm
SAR r, 10
end;
Result := r;
end;
function Turbulence2Dia(x, y: Integer; const n: Integer): Integer;
var
r, i: Integer;
a: Integer;
begin
r := 0;
a := 1;
for i := n - 1 downto 0 do
begin
Inc(r, Abs(Noise2Di(x, y)) div a);
x := x shl 1;
y := y shl 1;
a := a shl 1;
end;
Result := r;
end;
procedure FormCreate;
begin
MapSizeX := WndWidth;
MapSizeY := WndHeight;
Randomize;
bmg := HeapAllocate(MapSizeX * MapSizeY * SizeOf(Map[0]));
Map := HeapAllocate(MapSizeX * MapSizeY * SizeOf(Map[0]));
Map1 := HeapAllocate(MapSizeX * MapSizeY * SizeOf(Map1[0]));
HighMap := MapSizeX * MapSizeY - 1;
InitNoise;
end;
procedure GenerateMap(Map: PLongA; HighMap: LongInt; const SizeX, SizeY: Word;
ScaleX: Double = 0; ScaleY: Double = 0; Octaves: Integer = -1;
OffsetX: Double = 0; OffSetY: Double = 0);
var
x, y, i: Integer;
v: Integer;
Xi, Yi, DXi, DYi: Integer;
begin
if (SizeX * SizeY) = 0 then
Exit;
if HighMap <> (Sizex * SizeY - 1) then
Map := HeapAllocate(SizeX * SizeY * SizeOf(Map[0]));
if octaves < 0 then
Octaves := Round(Random * 8);
if ScaleX = 0 then
ScaleX := Sqrt(Random + 0.5);
if ScaleY = 0 then
ScaleY := Sqrt(Random + 0.5);
if OffsetX = 0 then
OffsetX := Random * 100;
if OffsetY = 0 then
OffsetY := Random * 100;
Xi := Round(OffsetX * 1024);
Yi := Round(OffsetY * 1024);
DXI := Round(1024 * ScaleX / SizeX);
DYI := Round(1024 * ScaleY / SizeY);
i := 0;
for y := 0 to SizeY - 1 do
begin
for x := SizeX - 1 downto 0 do
begin
v := Turbulence2Dia(XI, YI, Octaves) shr 2;
Map[i] := (v shl 16) + (v shl 8) + v;
Inc(i);
Inc(XI, DXI);
end;
XI := Round(OffsetX * 1024);
Inc(YI, DYI);
end;
end;
procedure ColorizeBaseMap(Map: PLongA; HighMap: LongInt; Color: Integer = 0);
var
Pal: array[0..255] of TRGBQuad;
R, G, B: Integer;
i: Integer;
begin
if Color <> 0 then
begin
R := (Color and $FF0000) shr 16;
G := (Color and $FF00) shr 8;
B := Color and $FF;
end
else
repeat
R := Round(Random * 255);
G := Round(Random * 255);
B := Round(Random * 255);
until (R + G + B) > 550;
for i := 0 to 255 do
with Pal[i] do
begin
Red := Round(Min((i * R) / 127, 255));
Green := Round(Min((i * G) / 127, 255));
Blue := Round(Min((i * B) / 127, 255));
end;
for i := 0 to HighMap do
Map[i] := LongWord(Pal[Map[i] and $FF]);
end;
procedure PowMap(Map: PLongA; HighMap: LongInt);
var
r, g, b, v, i: Integer;
begin
for i := 0 to HighMap do
begin
v := Map[i];
r := 255 - ((v and $FF0000) shr 16);
g := 255 - ((v and $FF00) shr 8);
b := 255 - (v and $FF);
r := r * r div 256;
g := g * g div 256;
b := b * b div 256;
Map[i] := r shl 16 + g shl 8 + b;
end;
end;
procedure MultMap(Map1, Map2: PLongA; HighMap: LongInt);
var
v, w, i: Integer;
rv, gv, bv, rw, gw, bw, r, g, b: Integer;
begin
for i := 0 to HighMap do
begin
v := Map1[i];
w := Map2[i];
rv := (v and $FF0000) shr 16;
gv := (v and $FF00) shr 8;
bv := v and $FF;
rw := (w and $FF0000) shr 16;
gw := (w and $FF00) shr 8;
bw := w and $FF;
r := Min(255, (((rv * 3) div 2 + 127) * rw) div 256);
g := Min(255, (((gv * 3) div 2 + 127) * gw) div 256);
b := Min(255, (((bv * 3) div 2 + 127) * bw) div 256);
Map1[i] := r shl 16 + g shl 8 + b;
end;
end;
procedure CreateMap;
var
x, y, i: LongWord;
Row: PRGBQuadA;
begin
GenerateMap(Map, HighMap, MapSizeX, MapSizeY);
ColorizeBaseMap(Map, HighMap);
PowMap(Map, HighMap);
GenerateMap(Map1, HighMap, MapSizeX, MapSizeY);
ColorizeBaseMap(Map1, HighMap);
PowMap(Map1, HighMap);
MultMap(Map, Map1, HighMap);
GenerateMap(Map1, HighMap, MapSizeX, MapSizeY);
ColorizeBaseMap(Map1, HighMap);
PowMap(Map1, HighMap);
MultMap(Map, Map1, HighMap);
i := 0;
for y := 0 to MapSizeY - 1 do
begin
Row := PRGBQuadA(LongWord(bmg) + y * MapSizeX * SizeOf(Map[0]));
for x := 0 to MapSizeX - 1 do
begin
Row[x] := TRGBQuad(Map[i]);
Inc(i);
end;
end;
end;
procedure FormPaint;
begin
CreateMap;
// DrawImageEx(bmg^, 0, 0, WndWidth, WndHeight, 32, nil, 0); // this line is equivalent to the line below
Blit(bmg^, 0, 0, WndWidth, WndHeight, 0, 0, WndWidth, WndHeight, WndWidth * SizeOf(TRGBQuad), BLIT_CLIENT_RELATIVE);
end;
begin
with GetScreenSize do
begin
WndHeight := Height;
WndWidth := Width;
end;
SetEventMask(EM_REDRAW or EM_KEY);
HeapInit;
FormCreate;
while True do
case CheckEvent of
REDRAW_EVENT:
begin
BeginDraw;
DrawWindow(0, 0, WndWidth, WndHeight, nil, 0, WS_NO_DRAW, CAPTION_NONMOVABLE);
EndDraw;
end;
KEY_EVENT:
Break;
else
FormPaint;
end;
end.
Я лишь адаптировал пример, так что, скорость генерации изображения зависит от мощности вашей системы.
Кстати, это не в первый раз уже, когда я нахожу на том французском сайте интересный пример.
Ранее уже был Plasma Effect Demo, но тогда я переписал исходный код с Delphi на ассемблер UASM.
Прикладываю уже скомпилированное приложение TextureGenerator.kex