OpenGL narzędzie dla bardzo ambitnych

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

OpenGL

narzędzie dla bardzo ambitnych

Robert Machejek

Instytut Informatyki

Uniwersytet Śląski w Katowicach

12 grudnia 2008

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

OpenGL - co to właściwie jest?

OpenGL (ang. Open Graphics Library) - specyfikacja uniwersalnego API
do generowania grafiki. Zestaw funkcji składa się z 250 podstawowych
wywołań, umożliwiających budowanie złożonych trójwymiarowych scen z
podstawowych figur geometrycznych.
OpenGL wykorzystywany jest często przez gry komputerowe i wygaszacze
ekranu, spełnia rolę analogiczną, jak konkurencyjny Direct3D (część
DirectX) w systemie Windows firmy Microsoft. Również programy do
przedstawiania wyników badań naukowych, CAD, oraz wirtualnej
rzeczywistości używają OpenGL.

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

OpenGL - krótka historia

Troszkę historii..

1992 - powstaje wersja 1.0 specyfikacji OpenGL przenośnej między
platformami. OpenGL Architecture Review Board (SG,HP,IBM)

1995 - wersja 1.1 tej biblioteki z wieloma poprawkami
przyśpieszającymi wyświetlanie grafiki.

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

No to na pewno warte uwagi

OpenGL nie należy do języków opisu sceny. Scena tworzona jest w
OpenGL z wielokątów poprzez wywoływanie odpowiednich procedur
Języki programowania:
Pascal,C/C++,Visual Basic,Python,Java

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

Składnia - bo jak bez niej żyć

Polecenia OpenGL określane są jako funkcje lub procedury. Znaczna cześć
funkcji wykonuje te same operacje, ale różni się zbiorem argumentów.
Przyjęta konwencja nazewnictwa określa ilość i rodzaj parametrów funkcji
według poniższego schematu:

rtype Name {1|2|3|4} {b|s|i|f|d|ub|us|ui} {v}

[

args, ]Targ1, ..., TargN[, args]

gdzie poszczególne elementy oznaczają:

rtype - wartość zwracana przez funkcje,

Name - nazwa funkcji,

1, 2, 3, 4 - ilość argumentów funkcji,

b - argumenty typu GLbyte,

s - argumenty typu GLshort,

... itd... czyli najnormalniej typy danych GLfloat, GLdouble, GLubyte, GLushort,
GLuint

v - argument funkcji stanowi tablica wartości,

T arg1, ..., T argN - argumenty funkcji.

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

Typy danych - aby ładnie na różnych platformach hulało

Typ

danych

OpenGL

min.

liczba

bitów

Opisik

GLboolean

1

typ logiczny

GLbyte

8

liczba całkowita ze znakiem (U2)

GLubyte

8

liczba całkowita bez znaku

GLchar

8

ciąg znaków tekstowych

GLshort

16

liczba całkowita ze znakiem (U2)

GLushort

16

liczba całkowita bez znaku

GLint

32

liczba całkowita ze znakiem (U2)

GLuint

32

liczba całkowita bez znaku

GLsizei

32

nieujemna liczba całkowita

GLenum

32

typ wyliczeniowy całkowity

GLintptr

ptrbits

wskaźnik na liczbę całkowitą ze znakiem (U2)

GLsizeiptr

ptrbits

wskaźnik na nieujemna liczbę całkowitą

GLbitfield

32

pole bitowe

GLfloat

32

liczba zmiennoprzecinkowa

GLclampf

32

liczba zmiennoprzecinkowa z przedziału [0, 1]

GLdouble

64

liczba zmiennoprzecinkowa

GLclampd

64

liczba zmiennoprzecinkowa z przedziału [0, 1]

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

Wady a może zalety

OpenGL nie ma funkcji obsługujących operacje:

wejścia/wyjścia

interakcje z użytkownikiem

zarządzanie oknami.

Wywołania funkcji w OpenGL są zgodne z konwencją wywoływania
funkcji w języku C.

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program

Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

No to narysujmy tło

Na dobry początek tworzymy klasę MyView

public class MyView : OpenGLControl

{

public MyView() : base()

{}

public override void glDraw()

{GL.glClear(GL.GL_COLOR_BUFFER_BIT);}

protected override void InitGLContext()

{base.InitGLContext();

GL.glClearColor( 0.0f, 0.0f, 1.0f, 0.0f );}

protected override void OnSizeChanged(EventArgs e)

{base.OnSizeChanged(e);}

}

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program

Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

No to narysujmy tło

Mamy już klasę to teraz wypada konstruktor ładny napisać

public class MyView : OpenGLControl

public Form1()

{

InitializeComponent();

this.ClientSize = new System.Drawing.Size(640, 480);

// Ustawiamy rozmiar widoku

this.view = new MyView();

// Tworzymy obiekt klasy MyView

this.view.Parent = this;

// Ustawiamy rodzica na gªówne okno aplikacji

this.view.Dock = DockStyle.Fill;

// B¦dziemy wypeªnia¢ caªy okno.

}

... a jeżeli komuś się wydaje że to już koniec to zapomniał o ...

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program

Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

No to narysujmy tło

...o metodzie main klasy Form1

static void Main()

{

Form1 form = new Form1();

form.Show();

while( !form.IsDisposed )

{

form.view.glDraw();

form.Refresh();

Application.DoEvents();

}

form.Dispose();

}

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program

Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

No to narysujmy tło

Na koniec wypadało by się pochwalić wynikami :D ...

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program

Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

No to narysujmy tło

... wiec się chwalimy

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program

Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

aby nie było bo mieliśmy się czegoś nauczyć

Przywołani do porządku dowiedzmy się co te dziwne znaczki na
wcześniejszych stronach oznaczają

glDraw()

- funkcja odpowiedzialna za wy±wietlanie. Standardowo

metoda ta jest wywoªywana na zdarzenie

Paint

.

InitGLContext()

- w tej metodzie przeprowadzane s¡ wszystkie

inicjacje jak np ustawienie koloru czyszczenia bufora kolorów.

OnSizeChanged()

- metoda obsªuguj¡ca zdarzenie zmiany rozmiaru

okna..

ClientSize

- ustawiamy rozmiar po obszaru roboczego po jakim

b¦dziemy rysowa¢.

view.Parent

- ustawiamy rodzica dla na gªówne okno. Dzi¦ki temu

okre±lamy gdzie b¦dziemy rysowa¢ za pomoc¡ klasy

MyView

.

viewDock

- okre±lany sposób wypeªnienia obszaru roboczego. W tym

przypadku ustawiamy wypeªnianie caªego okna.

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?

Napiszmy pierwszy program

Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

...a co namieszaliśmy w metodzie Main?

Po pierwsze usunęliśmy standardowe uruchomienie aplikacji. W tym
przypadku było to konieczne. Problem tkwi bowiem w nieustannym
odświeżaniu okna. Problem rozwiązaliśmy następująco:

tworzymy obiekt reprezentujący nasze okno głównego

wyświetlamy okno

wykonujemy pętle do momentu kiedy okno nie zostanie uznane za
niewłaściwą kontrolkę (następuje to np po wywołaniu komendy
zamknięcia aplikacji). W każdej iteracji wywołujemy metodą rysującą
klasy

MyView

, odświeżamy okno a następnie obsługujemy

komunikaty okna.

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program

Napiszmy coś ambitniejszego

to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

rysujemy trójkącik :D

W tym celu musimy naspidać metodę

Draw()

public override void Draw()

{

#region Draw Triangle

Gl.glPushMatrix();

base.Draw();

Gl.glBegin(Gl.GL_TRIANGLES);

// Rysowanie trójk¡ta

Gl.glColor4fv(colorTop);

Gl.glVertex3f(0.0f, (oat)(+height / 2), 0.0f);

// Wierzchoªek trójk¡ta

Gl.glColor4fv(colorLeftBottom);

Gl.glVertex3f((oat)(-xSize / 2), (oat)(-height / 2), 0.0f);

// Lewy bok trójk¡ta

Gl.glColor4fv(colorRightBottom);

Gl.glVertex3f((oat)(+xSize / 2), (oat)(-height / 2), 0.0f);

// ‘rodeczek trójk¡ta

Gl.glEnd();

// I to by byªo na tyle z trójk¡cikiem

Gl.glPopMatrix();

#endregion
}

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program

Napiszmy coś ambitniejszego

to jeszcze kwadracik w wersji dla ambitnych
Niedoceniani zróbmy coś ambitnego

rysujemy trójkącik cd..

Biorąc pod uwagę, że tym razem korzystamy z bogatej biblioteki

TaoFramework

w wyniku powyższej operacji powinniśmy otrzymać

poniższy efekt

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program
Napiszmy coś ambitniejszego

to jeszcze kwadracik w wersji dla ambitnych

Niedoceniani zróbmy coś ambitnego

rysujemy trójkącik cd..

Chcąc narysować kwadracik w wersji ambitniejszej wracamy do pierwszej
implementacji (niebieskie tło) i nadpisujemy klasy zgodnie ze schematem.

protected override void InitGLContext()

{ GL.glShadeModel(GL.GL_SMOOTH);
// gładkie cieniowanie
GL.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
// kolor czyszczenia bufora kolorów
GL.glClearDepth(1.0f);
// wartość wypełnienia bufora głębi
GL.glEnable(GL.GL_DEPTH_TEST);
GL.glDepthFunc(GL.GL_LEQUAL);
GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT,GL.GL_NICEST);

}

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program
Napiszmy coś ambitniejszego

to jeszcze kwadracik w wersji dla ambitnych

Niedoceniani zróbmy coś ambitnego

rysujemy kwadracik cd..

protected override void OnSizeChanged(EventArgs e)

{

base.OnSizeChanged(e);

// wywoªujemy metod¡ klasy bazowej

System.Drawing.Size s = Size;

// pobieramy nowy rozmiar okna

GL.glMatrixMode(GL.GL_PROJECTION);

GL.glLoadIdentity();

GL.gluPerspective(45.0f, (double)s.Width /(double) s.Height, 0.1f,

100.0f);

GL.glMatrixMode(GL.GL_MODELVIEW);

GL.glLoadIdentity();

}

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program
Napiszmy coś ambitniejszego

to jeszcze kwadracik w wersji dla ambitnych

Niedoceniani zróbmy coś ambitnego

rysujemy kwadracik cd..

public override void glDraw()

{ GL.glClear(GL.GL_COLOR_BUFFER_BIT); GL.glClear(GL.GL_COLOR_BUFFER_BIT |

GL.GL_DEPTH_BUFFER_BIT); GL.glMatrixMode(GL.GL_MODELVIEW); GL.glLoadIdentity(); GL.glTranslatef(0.0f,0.0f,-5.0f);
GL.glRotatef(xrot,1.0f,0.0f,0.0f); // obrót po osi X xrot+=0.3f; // zwiększenie kąta obrotu po osi X GL.glRotatef(yrot,0.0f,1.0f,0.0f); // obrót po osi Y
yrot+=0.2f; // zwiększenie kąta obrotu po osi Y GL.glRotatef(zrot,0.0f,0.0f,1.0f); // obrót po osi Z zrot+=0.4f; // zwiększenie kąta obrotu po osi Z
GL.glBegin(GL.GL_QUADS); // rozpoczęcie rysowania czworoboków
GL.glColor3f(1.0f, 0.0f, 0.0f); GL.glVertex3f(1.0f,1.0f,1.0f); // deklaracja koloru i wierzchołka
GL.glColor3f(1.0f, 0.0f, 0.0f); GL.glVertex3f(-1.0f,1.0f,1.0f)
GL.glColor3f(1.0f, 0.0f, 0.0f); GL.glVertex3f(-1.0f,-1.0f,1.0f);
GL.glColor3f(1.0f, 0.0f, 0.0f); GL.glVertex3f(1.0f,-1.0f,1.0f);
GL.glColor3f(0.0f, 1.0f, 0.0f); GL.glVertex3f(-1.0f,1.0f,-1.0f);
GL.glColor3f(0.0f, 1.0f, 0.0f); GL.glVertex3f(1.0f,1.0f,-1.0f);
GL.glColor3f(0.0f, 1.0f, 0.0f); GL.glVertex3f(1.0f,-1.0f,-1.0f);
GL.glColor3f(0.0f, 1.0f, 0.0f); GL.glVertex3f(-1.0f,-1.0f,-1.0f);
GL.glColor3f(0.0f, 0.0f, 1.0f); GL.glVertex3f(1.0f,1.0f,-1.0f);
GL.glColor3f(0.0f, 0.0f, 1.0f); GL.glVertex3f(-1.0f,1.0f,-1.0f);
GL.glColor3f(0.0f, 0.0f, 1.0f); GL.glVertex3f(-1.0f,1.0f,1.0f);
GL.glColor3f(0.0f, 0.0f, 1.0f); GL.glVertex3f(1.0f,1.0f,1.0f);
GL.glColor3f(1.0f, 0.0f, 1.0f); GL.glVertex3f(1.0f,-1.0f,1.0f);
GL.glColor3f(1.0f, 0.0f, 1.0f); GL.glVertex3f(-1.0f,-1.0f,1.0f);
GL.glColor3f(1.0f, 0.0f, 1.0f); GL.glVertex3f(-1.0f,-1.0f,-1.0f);
GL.glColor3f(1.0f, 0.0f, 1.0f); GL.glVertex3f(1.0f,-1.0f,-1.0f);
GL.glColor3f(0.0f, 1.0f, 1.0f); GL.glVertex3f(1.0f,1.0f,-1.0f);
GL.glColor3f(0.0f, 1.0f, 1.0f); GL.glVertex3f(1.0f,1.0f,1.0f);
GL.glColor3f(0.0f, 1.0f, 1.0f); GL.glVertex3f(1.0f,-1.0f,1.0f);
GL.glColor3f(0.0f, 1.0f, 1.0f); GL.glVertex3f(1.0f,-1.0f,-1.0f);
GL.glColor3f(1.0f, 1.0f, 0.0f); GL.glVertex3f(-1.0f,1.0f,1.0f);
GL.glColor3f(1.0f, 1.0f, 0.0f); GL.glVertex3f(-1.0f,1.0f,-1.0f);
GL.glColor3f(1.0f, 1.0f, 0.0f); GL.glVertex3f(-1.0f,-1.0f,-1.0f);
GL.glColor3f(1.0f, 1.0f, 0.0f); GL.glVertex3f(-1.0f,-1.0f,1.0f);
GL.glEnd(); // koniec rysowania
}

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program
Napiszmy coś ambitniejszego

to jeszcze kwadracik w wersji dla ambitnych

Niedoceniani zróbmy coś ambitnego

rysujemy kwadracik cd..

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych

Niedoceniani zróbmy coś ambitnego

ambitnego Bohachevskiego narysujmy

Zaczynamy standardowo - nadpisujemy klasy do czego zdążyliśmy się już
chyba przyzwyczaić.

protected override void InitGLContext()

{

GL.glShadeModel(GL.GL_SMOOTH); // gªadkie cieniowanie

GL.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // kolor czyszczenia bufora

kolorów

GL.glClearDepth(1.0f); // warto±¢ wypeªnienia bufora gª¦bi

GL.glEnable(GL.GL_DEPTH_TEST); // uaktywnienie testu gª¦bi

GL.glDepthFunc(GL.GL_LEQUAL); // rodzaj funkcji testuj¡cej gª¦bie

GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);

BuildLists();
}

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych

Niedoceniani zróbmy coś ambitnego

ambitnego Bohachevskiego narysujmy

Nadpisujmy dalej - w końcu wersja dla ambitnych ma być

protected override void OnSizeChanged(EventArgs e)

{

{

base.OnSizeChanged(e); // wywoªujemy metod¡ klasy bazowej

System.Drawing.Size s = Size; // pobieramy nowy rozmiar okna

GL.glMatrixMode(GL.GL_PROJECTION);

GL.glLoadIdentity();

GL.gluPerspective(45.0f, (double)s.Width / (double)s.Height, 0.1f,

100.0f);

GL.glMatrixMode(GL.GL_MODELVIEW)

ustalamy widok;

GL.glLoadIdentity();
}

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych

Niedoceniani zróbmy coś ambitnego

ambitnego Bohachevskiego narysujmy

Teraz utworzymy sobie klasę którą sobie porysujemy

public void DrawGraph(int functionNumber)

{ {

float r = 0, g = 0, b = 0;
GetData(bohachevsky f1.dat); break; }
GL.glBegin(GL.GL_QUAD_STRIP);
for (int layer = 0; layer < 10; layer++)
{
for (int i = 0; i < pointCount; i++)
{
if (zTable[i] < 0)
GL.glColor3f(0.0f, 0.6f, 1.0f);
else
GL.glColor3f(0.0f, 0.3f, 1.0f);
GL.glVertex3f(xTable[i], zTable[i], yTable[i]);
GL.glVertex3f(xTable[i + layer * pointCount], zTable[i + layer * pointCount], yTable[i + layer * pointCount]);
if (i == 96)
{
i = i + 2;
GL.glEnd();
GL.glBegin(GL.GL_QUAD_STRIP);
}
{ r = r + 0.01f; g = g + 0.01f; b = b + 0.01f; }
i++;
}
}
GL.glEnd(); }) }

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych

Niedoceniani zróbmy coś ambitnego

Magiczny plik

bohachevsky f1.dat

Magiczny pliczek to nic innego jak współrzędne które posłużą do
wyrysowania funkcji oraz typ zmiennej

#x y z type -50 -50 7500 GLint

-48.9899 -50 7400.61 GLint

-47.9798 -50 7302.07 GLint

-46.9697 -50 7206.74 GLint

-45.9596 -50 7112.31 GLint

-44.9495 -50 7021.02 GLint

-43.9394 -50 6930.72 GLint

-42.9293 -50 6843.46 GLint

-41.9192 -50 6757.3 GLint

-40.9091 -50 6674.05 GLint

-39.899 -50 6592.06 GLint

-38.8889 -50 6512.8 GLint

-37.8788 -50 6434.98 GLint

... ... ... ...

-29.798 -50 5888.32 GLint

-28.7879 -50 5828.92 GLint

-27.7778 -50 5772.05 GLint

-26.7677 -50 5716.63 GLint

-25.7576 -50 5663.95 GLint

... ... ... ...

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

OpenGL - co? kto? kiedy?
Napiszmy pierwszy program
Napiszmy coś ambitniejszego
to jeszcze kwadracik w wersji dla ambitnych

Niedoceniani zróbmy coś ambitnego

wynik końcowy wcześniejszego kodu

Czyli ładny wykresik dostaliśmy

Robert Machejek

OpenGL

background image

Open GL

Podsumowanie

Podsumowanie

Reasumując olbrzymią zaletą OpenGL jest wizualizacja (takie ładne
wszystko). Wodą jest z całą pewnością skomplikowana składnia.
Dziękuje za uwagę

Robert Machejek

OpenGL


Document Outline


Wyszukiwarka

Podobne podstrony:

więcej podobnych podstron