Programowanie układów graficznych

Podobne dokumenty
OpenGL. Silicon Graphics (IRIS GL stacje graficzne)

glwindowpos2d void DrawString (GLint x, GLint y, char *string) { glwindowpos2i (x,y); int len = strlen (string); for (int i = 0; i < len; i++)

Temat: Transformacje 3D

3 Przygotował: mgr inż. Maciej Lasota

Zatem standardowe rysowanie prymitywów wygląda następująco:

OpenGL Światło (cieniowanie)

OpenGL Światło (cieniowanie)

Efekt lustra 3D w OpenGL z wykorzystaniem bufora szablonowego (stencil buffer)

OpenGL model oświetlenia

Elementarne obiekty geometryczne, bufory. Dorota Smorawa

Co to jest OpenGL? Oprogramowanie i wykorzystanie stacji roboczych. Wykład 5. OpenGL - Achitektura. OpenGL - zalety. olas@icis.pcz.

Grafika 3D OpenGL część II

OpenGL przezroczystość

Oprogramowanie i wykorzystanie stacji roboczych. Wykład 5

OpenGL teksturowanie

GRAFIKA KOMPUTEROWA 8: Konwersja i mieszanie kolorów

Janusz Ganczarski. OpenGL Pierwszy program

Zadanie 1. Ściana. 1. Potrzebne zmienne w dołączonym do zadania kodzie źródłowym

2 Przygotował: mgr inż. Maciej Lasota

GRAFIKA KOMPUTEROWA 10: Antyaliasing

Teksturowanie. Oprogramowanie i wykorzystanie stacji roboczych. Wykład 10. Tekstury. Proces nakładania tekstury.

Wprowadzenie do programowania z wykorzystaniem biblioteki OpenGL. Dorota Smorawa

Studium podyplomowe. Programowanie w OpenGL. Michał Turek, AGH Kraków

Oprogramowanie i wykorzystanie stacji roboczych. Wykład 6

Laboratorium grafiki komputerowej i animacji. Ćwiczenie V - Biblioteka OpenGL - oświetlenie sceny

Oświetlenie w OpenGL. Oprogramowanie i wykorzystanie stacji roboczych. Wykład 8. Światło otaczajace. Światło rozproszone.

dr inż. Jacek Dąbrowski, KSG

GRAFIKA KOMPUTEROWA 7: Kolory i cieniowanie

Plan wykładu. Akcelerator 3D Potok graficzny

Grafika Komputerowa Wykład 5. Potok Renderowania Oświetlenie. mgr inż. Michał Chwesiuk 1/38

Bufor koloru cd. Czyszczenie bufora koloru glclearcolor( )

GRAFIKA CZASU RZECZYWISTEGO Wprowadzenie do OpenGL

0. OpenGL ma układ współrzędnych taki, że oś y jest skierowana (względem monitora) a) w dół b) w górę c) w lewo d) w prawo e) w kierunku do

6 Przygotował: mgr inż. Maciej Lasota

Temat: Wprowadzenie do OpenGL i GLUT

Grafika Komputerowa Wykład 6. Teksturowanie. mgr inż. Michał Chwesiuk 1/23

Światło. W OpenGL można rozróżnić 3 rodzaje światła

Mieszanie kolorów. Dorota Smorawa

Materiały. Dorota Smorawa

OpenGL oświetlenie. Bogdan Kreczmer. Katedra Cybernetyki i Robotyki Wydziału Elektroniki Politechnika Wrocławska

1 Wstęp teoretyczny. Temat: Manipulowanie przestrzenią. Grafika komputerowa 3D. Instrukcja laboratoryjna Układ współrzędnych

OpenGL - charakterystyka

Laboratorium Grafiki Komputerowej i Animacji. Ćwiczenie V. Biblioteka OpenGL - oświetlenie sceny

1. Prymitywy graficzne

8 Przygotował: mgr inż. Maciej Lasota

Laboratorium Grafiki Komputerowej i Animacji. Ćwiczenie VI. Biblioteka OpenGL - teksturowanie

Tekstury. Dorota Smorawa

Grafika Komputerowa Wykład 4. Synteza grafiki 3D. mgr inż. Michał Chwesiuk 1/30

Rzutowanie DOROTA SMORAWA

Laboratorium Grafiki Komputerowej i Animacji. Ćwiczenie VI. Biblioteka OpenGL - teksturowanie

Programowanie Procesorów Graficznych

Laboratorium 1. Część I. Podstawy biblioteki graficznej OpenGL.

GRK 4. dr Wojciech Palubicki

Janusz Ganczarski. OpenGL Definiowanie sceny 3D

Druga aplikacja Prymitywy, alpha blending, obracanie bitmap oraz mały zestaw przydatnych funkcji wyświetlających własnej roboty.

Wykład 4. Rendering (1) Informacje podstawowe

Synteza i obróbka obrazu. Tekstury. Opracowanie: dr inż. Grzegorz Szwoch Politechnika Gdańska Katedra Systemów Multimedialnych

System graficzny. Potok graficzny 3D. Scena 3D Zbiór trójwymiarowych danych wejściowych wykorzystywanych do wygenerowania obrazu wyjściowego 2D.

Programowanie gier komputerowych Tomasz Martyn Wykład 6. Materiały informacje podstawowe

Wstęp Podstawy Pierwszy program Definiowanie sceny 3D Przekształcenia geometryczne... 47

Ustawienia materiałów i tekstur w programie KD Max. MTPARTNER S.C.

Światła i rodzaje świateł. Dorota Smorawa

OpenGL - maszyna stanu. Oprogramowanie i wykorzystanie stacji roboczych. Wykład 7. Grupy atrybutów. Zmienne stanu.

Rysowanie punktów na powierzchni graficznej

Teksturowanie (ang. texture mapping)

Podstawy Informatyki Wykład V

GLKit. Wykład 10. Programowanie aplikacji mobilnych na urządzenia Apple (IOS i ObjectiveC) #import "Fraction.h" #import <stdio.h>

OpenGL i wprowadzenie do programowania gier

Animowana grafika 3D. Opracowanie: J. Kęsik.

Laboratorium 4 OpenGl (4) Oświetlenie sceny

Specyfikacja OpenGL Podstawy programowania grafiki komputerowej*

Prosty program- cpp. #include <GL/glut.h>

RENDERING W CZASIE RZECZYWISTYM. Michał Radziszewski

OpenGL Zaawansowana grafika komputerowa

Wykład 12. Wprowadzenie do malarstwa, str. 1 OpenGL Open Graphics Library. OpenGL składa się z

Wprowadzenie. Artur Staszczyk Bartłomiej Filipek

Przekształcenia geometryczne. Dorota Smorawa

Julia 4D - raytracing

GRAFIKA RASTROWA. WYKŁAD 1 Wprowadzenie do grafiki rastrowej. Jacek Wiślicki Katedra Informatyki Stosowanej

GRAFIKA KOMPUTEROWA. Plan wykładu. 1. Początki grafiki komputerowej. 2. Grafika komputerowa a dziedziny pokrewne. 3. Omówienie programu przedmiotu

1 Temat: Vertex Shader

Wykład 12. Wprowadzenie do malarstwa, str. 1 OpenGL Open Graphics Library. OpenGL składa się z

GRAFIKA CZASU RZECZYWISTEGO Podstawy syntezy grafiki 3D i transformacji geometrycznych

Efekty dodatkowe w rasteryzacji

Oświetlenie obiektów 3D

Bartłomiej Filipek

Wybrane aspekty teorii grafiki komputerowej - dążenie do wizualnego realizmu. Mirosław Głowacki

Obsługa mapy przy użyciu narzędzi nawigacji

Filtrowanie tekstur. Kinga Laurowska

Podstawy grafiki komputerowej

Wybrane aspekty teorii grafiki komputerowej - dążenie do wizualnego realizmu. Mirosław Głowacki

RENDERING W CZASIE RZECZYWISTYM. Michał Radziszewski

Transformacje. dr Radosław Matusik. radmat

Wprowadzenie do rysowania w 3D. Praca w środowisku 3D

Trójwymiarowa grafika komputerowa rzutowanie

WIZUALIZACJA INFORMACJI TEKSTOWEJ WSTĘP DO HTML 5 CANVAS

Grafika Komputerowa Wybrane definicje. Katedra Informatyki i Metod Komputerowych Uniwersytet Pedagogiczny im. KEN w Krakowie apw@up.krakow.

Oświetlenie. Modelowanie oświetlenia sceny 3D. Algorytmy cieniowania.

Grafika komputerowa INSTRUKCJA DO LABORATORIUM 2: operacje przestrzenne oraz obsługa klawiatury i myszki

OpenGL - tekstury Mapowanie tekstur

Transkrypt:

Programowanie układów graficznych Autor: Aleksander Dawid Wykład + Labolatorium 1. OpenGL obsługa podstawowej funkcjonalności GPU 2. GLSL programowanie przetwornika wierzchołków i fragmentów 3. CUDA programowanie ogólnego przeznaczenia 4. OpenCL rozwiązanie niezależne od sprzętu. Aleksander Dawid 2001-2016 rok 1

OpenGL Silicon Graphics (IRIS GL stacje graficzne) Biblioteka -przestrzeń 3D -rzutowanie -prymitywy graficzne -operacje na barwach HISTORIA 1992 - powstaje wersja 1.0 specyfikacji OpenGL przenośnej między platformami. OpenGL Architecture Review Board (SG,HP,IBM) Aleksander Dawid 2001-2012 rok 2

OpenGL 1995 - wersja 1.1 tej biblioteki z wieloma poprawkami przyśpieszającymi wyświetlanie grafiki. 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 Aleksander Dawid 2001-2012 rok 3

OpenGL (WINDOWS) OpenGL nie ma funkcji obsługujących operacje: -wejścia/wyjścia -interakcje z użytkownikiem -zarządzanie oknami. WINDOWS Wprowadzono w wersjach Win95 OSR2 WinNT 3.51/4.0 Obsługa okien w OpenGL - funkcje wiggle. Aleksander Dawid 2001-2012 rok 4

OpenGL (AUX) Wywołania funkcji w OpenGL są zgodne z konwencją wywoływania funkcji w języku C. Biblioteki w systemie WIN32 glaux.lib - Auxiliary(pomocnicza)przenośna glaux.h przedrostek funkcji: aux opengl32.dll gl.h gl glu32.dll glu.h glu Aleksander Dawid 2001-2012 rok 5

OpenGL (AUX) Biblioteka aux raczej jest pewną osnową dla wywoływania f. OpenGL. Zaletą jej jest to, że na każdej platformie wygląda ona tak samo. OpenGl32.dll właściwe wywołania OpenGL. Glu32.dll biblioteka pomocnicza rysowanie skomplikowanych obiektów cylindry, walce, NURBS. Aleksander Dawid 2001-2012 rok 6

OpenGL (Typy danych) OpenGL w celu przenośności między platformami wprowadza swoje typy danych. Glbyte,Glshort,Glint,Glsize,Glfloat, Glclampf,Gldouble,Glclampd,Glubyte, Glboolean,Glushort, Gluint, Glenum, Glbitfield. glclamp - color amplitude Aleksander Dawid 2001-2012 rok 7

OpenGL (Konwencje nazw) <Przedrostek biblioteki><rdzeń polecenia><opcjonalnie liczba argumentów><opcjonalnie typ argumentów> glcolor3f(...) gl - gl.h Color - nazwa 3f - 3 argumenty float. Aleksander Dawid 2001-2012 rok 8

OpenGL (Biblioteka aux) Przewidziana jako wspomaganie dla OpenGL w postaci implementacji przenośnej między systemami. Podstawowe operacje inicjalizujace wej/wyj. Aleksander Dawid 2001-2012 rok 9

OpenGL (kod aux) #include <windows.h> #include <gl\gl.h> #include <gl\glaux.h> void CALLBACK RenderScene(void) { glclearcolor(0.0f, 0.0f, 1.0f, 1.0f); glclear(gl_color_buffer_bit); glcolor3f(1.0f, 0.0f, 0.0f); glrectf(100.0f, 150.0f, 150.0f, 100.0f); glflush(); } void main(void) { auxinitdisplaymode(aux_single AUX_RGBA); auxinitposition(100,100,450,450); auxinitwindow("test2"); auxmainloop(renderscene); } Aleksander Dawid 2001-2012 rok 10

OpenGL (kod aux) auxinitdisplaymode(aux_single AUX_RGBA); Tryb wyświetlania: AUX_SINGLE - pojedynczy bufor AUX_RGBA - tryb kolorów. auxinitposition(100,100,450,450); Pozycja i wymiary okna. auxinitwindow("test2"); Nazwa okna auxmainloop(renderscene); Główna pętla renderowania obrazu. Aleksander Dawid 2001-2012 rok 11

OpenGL (kod aux) glclearcolor(0.0f, 0.0f, 1.0f, 1.0f); Kolor używany do czyszczenia ekranu. Krok koloru - 0.00006 glclear(gl_color_buffer_bit); Wykonanie czyszczenia ekranu. glcolor3f(1.0f, 0.0f, 0.0f); kolor rysowania. glrectf(100.0f, 150.0f, 150.0f, 100.0f); rysujemy prostokąt. Aleksander Dawid 2001-2012 rok 12

OpenGL (kod aux) glflush(); Przetwarzaj dotychczasowe komendy. Nagłówki #include <windows.h> #include <gl\gl.h> #include <gl\glaux.h> Aleksander Dawid 2001-2012 rok 13

Skalowanie okna wyświetlania. Nasz rysunek jest w rzeczywistości w przestrzeni 3D z=0. Przy zmianie wymiarów okna wyświetlania nasz obrazek też powinien być odpowiednio przeskalowany. Do tego służy funkcja auxreshapefunc(far* func), gdzie argumentem jest funkcja zwrotna o następującym prototypie. void CALLBACK ChangeSize(Glsizei w, Glsizei h) funkcja ta otrzymuje wysokość i szerokość z okna macierzystego przy każdej próbie przeskalowania go. Aleksander Dawid 2001-2012 rok 14

Skalowanie okna wyświetlania. Możemy użyć tego do odwzorowania naszego układu współrzędnych na układ współrzędnych ekranu za pomocą funkcji; DEFINIOWANIE WIDOKU glviewport(glint x,glint y, Glint w, Glint h); x,y - prawy dolny róg widoku w,h - szerokość, wysokość Aleksander Dawid 2001-2012 rok 15

Skalowanie okna wyświetlania. DEFINIOWANIE BRYŁY OBCINANIA Po zmianie rozmiaru okna musimy przedefniować bryłę obcinania aby stosunki współrzędnych zostały takie same. Stosunek współrzędnych (aspect ratio) to stosunek ilości pixeli odpowiadający jednostce osi pionowej do ilości pikseli na osi poziomej. 1.0 równe ilości pikseli na osiach. Rzutowanie równoległe glortho(gldouble lewa, Gldouble prawa, GLdouble dolna, GLdouble górna, Gldouble blizsza, Gldouble dalsza); Aleksander Dawid 2001-2012 rok 16

Skalowanie okna wyświetlania. DEFINIOWANIE BRYŁY OBCINANIA glloadidentity(); - macierz jdnostkowa. glortho() modyfikuje istniejące obcinanie. Void CALLBACK ChangeSize(Glsizei w, Glsizei h){ if(h==0) h=1; glviewport(0,0,w,h); glloadidentity(); if(w<=h) glortho(0.0f, 250.0f, 0.0f, 250.0f*h/w, 1.0,-1.0); else glortho(0.0f, 250.0f*w/h, 0.0f, 250.0f, 1.0,-1.0); } auxreshapefunc(changesize); Aleksander Dawid 2001-2012 rok 17

Animacje. Animacje w bibliotece pomocniczej osiągamy przez funkcje; auxidlefunction() gdzie argumentem jest funkcja o prototypie void CALLBACK IdleFunction(void); Funkcja jest wywoływana w momencie bezczynności programu. Nie jest wywoływana w momencie skalowania okna. Z animacją wiąże się problem wyświetlania. Najczęściej wyświetlanie nie nadąża za procesem rysowania co przejawiać się może w miganiu rysowanego obiektu. Aleksander Dawid 2001-2012 rok 18

Animacje. W celu uniknięcia takiego zjawiska stosuje się podwójne buforowanie. Obraz naszej sceny nie jest rysowany na bufor ekranu tylko do pomocniczego bufora, a z niego dopiero a ekran. auxdisplaymode(aux_double,aux_rgba) auxswapbuffers(); Aleksander Dawid 2001-2012 rok 19

Klawiatura. Biblioteka AUX pozwala nam modyfikować naszą scenę przez klawisze. auxkeyfunc(glint key, void(*func()); void CALLBACK KeyFunc(void); AUX_ESCAPE AUX_SPACE AUX_LEFT AUX_RIGHT AUX_UP AUX_DOWN Aleksander Dawid 2001-2012 rok 20

Mysz. Biblioteka AUX pozwala nam na interakcje z naszą sceną prze mysz. auxmousefunc(glint button, Glint mode void(* MouseFunc()); PROTOTYP void CALLBACK MouseFunc(AUX_EVENTREC *event); typedef struct _AUX_EVENTREC{ GLint event; Glint data[4]; }AUX_EVENTREC event - AUX_MOUSEUP,AUX_MOUSEDOWN data[aux_mousex]=pozioma współrzędna myszy data[aux_mousey]=pionowa współrzędna myszy data[mouse_status]=przycisk myszy (button param) Aleksander Dawid 2001-2012 rok 21

OpenGL (kod glut) Nagłówki #include <windows.h> #include <gl\gl.h> #include <gl\glut.h> int main(int argc, char **argv) { glutinit(&argc, argv); // GLUT inicjalizacja glutinitdisplaymode(glut_rgb GLUT_DOUBLE GLUT_DEPTH ); // Wyświetlanie glutinitwindowsize(640,480);// rozmiar okna glutcreatewindow("opengl/glut Window.");// utworzenie Okna glutdisplayfunc(display);// Wyświetlenie funkcji glutidlefunc( display );// Wyświetlanie w fazie bezczynności (Animacje) glutkeyboardfunc( keyboard );// Obsługa klawiszy glutmainloop();// główna pętla GLUT return 0; } Aleksander Dawid 2001-2012 rok 22

Prymitywy graficzne. (2) Rysowanie w 3 wymiarach. Układ współrzędnych określa nam bryła obcinania (glortho). (-100,100) 1. Trójwymiarowy punkt: wierzchołek glvertex2f(10.0f, 10.0f); glvertex3f(10.0f, 10.0f, 0.0f); glvertex4f(10.0f, 10.0f, 0.0f, 1.0f); w - współczynnik skalowania. Aleksander Dawid 2001-2012 rok 23

Prymitywy graficzne. Teraz mamy wierzchołek, wystarczy nam teraz określić czy ten wierzchołek będzie punktem, wierzchołkiem odcinka czy też jakiegoś wieloboku. Zadania wierzchołków grupujemy w pętli. glbegin(glenum mode)... glend() Zestaw punktów w 3D. glbegin(gl_points); glvertex3f(10.0f, 10.0f, 0.0f); glvertex3f(10.0f, 1.0f, 0.0f); glend(); Aleksander Dawid 2001-2012 rok 24

Prymitywy graficzne. Pamiętać trzeba o tym że punkt jest rysowany aktualnie wybranym kolorem. W pętli glbegin/glend można zawrzeć dowolną liczbę prymitywów. Ponawianie ustawiania prymitywu powoduje spowolnienie całego procesu tworzenia grafiki. glbegin(gl_points); for(i=0;i<10;i++) { x+=0.1; y+=0.1; glvertex3f(x,y,0.0f); } glend(); Aleksander Dawid 2001-2012 rok 25

Prymitywy graficzne. Ustalenie rozmiaru punktu. Domyślny rozmiar punktu to 1 pixel. Void glpointsize(glfloat size); size -średnica w pixelach rysowanego punktu. MS GL obsługuje wielkości od 0.05 do 10.0 co 0.125 GLfloat sizes[2]; GLfloat step; glgetfloatv(gl_point_size_range,sizes); glgetflotav(gl_point_size_granularity,&step); Wywołania te dotyczą maszyny stanu OpenGL Aleksander Dawid 2001-2012 rok 26

Prymitywy graficzne Rysowanie linii w 3 wymiarach. glbegin(gl_lines) glvertex3f(0.0,0.0,0.0); glvertex3f(50.0,50.0,50.0); glend(); Musimy podawać parzystą liczbę wierzchołków. Inaczej ostatni wierzchołek będzie ignorowany. Łamana GL_LINE_STRIP glbegin(gl_line_strip) glvertex3f(0.0,0.0,0.0); glvertex3f(50.0,50.0,50.0); glvertex3f(50.0,10.0,50.0); glend(); Aleksander Dawid 2001-2012 rok 27

Prymitywy graficzne Łamana zamknięta GL_LINE_LOOP glbegin(gl_line_loop) glvertex3f(0.0,0.0,0.0); glvertex3f(50.0,50.0,50.0); glvertex3f(50.0,10.0,50.0); glend(); Po napotkaniu ostatniego punktu krzywa jest zamykana. Ustalenie grubości linii. gllinewidth(glfloat width) Informacje o szerokości możemy uzyskać z maszyny stanu OpenGL. Aleksander Dawid 2001-2012 rok 28

Prymitywy graficzne glgetfloatv(gl_line_width_range,sizes); glgetfloatv(gl_line_width_ggranularity,&size); Linie przerywane. glenable(gl_line_stipple); gllinestipple(glint factor, Glushort pattern); Wyłączamy za pomocą gldisable(); pattern 16-bit 0000000011111111 = 0x00FF = 255; factor służy jako mnożnik zwiększający szerokość wzoru. Aleksander Dawid 2001-2012 rok 29

Prymitywy graficzne Rysowanie wielokątów w przestrzeni 3D. Trójkąt. glbegin(gl_triangles) glvertex3f(0.0,0.0,0.0); glvertex3f(25.0,25.0,0.0); glvertex3f(50.0,0.0,0.0); glend(); Kolejność określa nam kierunek rysowanego trójkąta. Zgodnie ze wskazówkami zegara lub przeciwnie. OpenGL zakłada, że wielokąty skierowane przeciwnie do wskazówek zegara są do nas zwrócone przodem. Jeśli chcesz to zmienić to glfrontface(gl_cw); GL_CCW Aleksander Dawid 2001-2012 rok 30

Prymitywy graficzne Rysowanie paska trójkątów. GL_TRIANGLE_STRIP Ilość wierzchołków może być większa od 3. Kolejność wierzchołków nie jest zachowana. Anticlockvise - kierunek przeciwny do wskazówek zegara musi być zachowany. Wachlarze trójkątów. GL_TRIANGLE_FAN Opcja ta służy do tworzenia zbioru trójkątów o wspólnym punkcie. Pierwszy wierzchołek wyznacza wspólny punkt dla wachlarza trójkątów. Aleksander Dawid 2001-2012 rok 31

Prymitywy graficzne (jednolite obiekty) Prze tworzeniu złożonych obiektów musimy się zastanowić nad tym jaki jest nasz obiekt. O kolorze wielokąta decyduje pirwszy wierzchołek w wielokącie, przy modelu w którym kolor jest jednolity. Wybór modelu koloru. glshademodel(gl_flat); - jednolity kolor glshademodel(gl_smooth); - interpolacja kolorów pośrednich. glbegin(gl_triangles) glcolor3f(1.0f,0.0f,0.0f); glvertex3f(0.0,0.0,0.0); glvertex3f(25.0,25.0,0.0); glvertex3f(50.0,0.0,0.0); glend(); Aleksander Dawid 2001-2012 rok 32

Prymitywy graficzne (bufor głębokości) W OpenGL obiekt rysowany jako drugi zawsze przesłania obiekt pierwszy. Problem ten można usunąć dzięki technice zwanej buforem głębokości. glenable(gl_depth_test); Testowane są pixele aby wyznaczyć te które są bliżej od tych które są dalej. W celu poprawy wydajności programu stosuje się nie rysowanie tylnych powierzchni. Aleksander Dawid 2001-2012 rok 33

Prymitywy graficzne (usuwanie niewidocznych). Eliminacja wielokątów skierowanych tyłem nazywa się usuwaniem niewidocznych powierzchni. glenable(gl_cull_face); Wielokąty mogą być rysowane jako siatki lub wypełnione. glpolygonmode(gl_front_and_back,gl_line); glpolygonmode(gl_back,gl_fill); Można to ustawiać zarówno dla tyłu jak i przodu. Aleksander Dawid 2001-2012 rok 34

Prymitywy graficzne (usuwanie niewidocznych) Czworokąty. GL_QUADS GL_QUAD_STRIP - pasek wielokątów. Ogólne wielokąty. GL_POLYGON może być używany do rysowania wielokąta o dowolnej liczbie krawędzi. Wypełnianie jednolitych wielokątów. Mapowanie tekstur. Określanie desenia. glenable(gl_polygon_stipple); glpolygonstipple(pbitmap); Aleksander Dawid 2001-2012 rok 35

Prymitywy graficzne (desenie) Wskaźnik do obszaru danych zawierający dane desenia. Glubyte *pbitmap; pbitmap=new Glubyte[16] 32bit x 32bit delete[] pbitmap; Warunki konstruowania wielokątów to 1. Nie wolno produkować wygiętych wielokątów. 2. Tylko wielokąty wypukłe. Aleksander Dawid 2001-2012 rok 36

Prymitywy graficzne (krawędzie). Figury wklęsłe można także konstruować w OpenGl składając je z kilku figur wypukłych. Gdy chcemy zachować krawędzie zewnętrzne jako widoczne to wystarczy podać czy ta krawędź należeć będzie do krawędzi zewnętrznych czy też nie. gledgeflag(true/false); glvertex2f(-20.0f,0.0f); Aleksander Dawid 2001-2012 rok 37

Przekształcenia w 3D Umożliwiają rzutowanie trójwymiarowych współrzędnych na dwuwymiarowy ekran. Najpierw musimy określić położenie obserwatora. Są to bezwzględne współrzędne ekranowe. Przekształcenie punktu obserwacji. Odpowiada ustawieniu i skierowaniu kamery na scenę. Przekształcenie modelu. Aleksander Dawid 2001-2012 rok 38

Przekształcenia w 3D (rzutowanie) Rzutowanie definiuje bryłę widzenia i definiuje bryłę obcinania. Równoległe glortho(..) równoległa bryła rzutowania -------------------------------- Perspektywiczne Ostrosłup widzenia w kierunku oka. glfrustum(gldouble left,right,bottom,top,near,far) - mnoży bieżącą macierz przez macierz rzutowania perspektywicznego. Aleksander Dawid 2001-2012 rok 39

Przekształcenia w 3D (rzutowanie) Znacznie lepszym rozwiązaniem jest funkcja void gluperspective(gldouble fovy, Gldouble aspect, Gldouble znear, Gldouble zfar) fovy - kąt pola widzenia w kierunku pionowym. Aspect - stosunek wysokości do szerokości bryły znear,zfar - odległości od bliższej i dalszej płaszczyzny. Dodatkowo co nam oferuje utility to funkcja glulookat(okox,okoy,okoz,punktx,punkty,punktz, gorax,goray,goraz); Pozwala ona na umieszczenie oka kamery w dowolnym punkcie. Aleksander Dawid 2001-2012 rok 40

Przekształcenia w 3D (rzutowanie) Rzutowanie definiuje bryłę widzenia i definiuje bryłę obcinania. Macierz widoku modelu 4x4 V*M=V Translacje. void gltranslatef(glfloat x, Glfloat y, Glfloat z) gltranslatef(0.0,10.0,0.0); Aleksander Dawid 2001-2012 rok 41

Przekształcenia w 3D (rzutowanie) Obroty. glrotatef(glfloat angle, Glfloat x, Glfloat y, Glfloat z); Kierunek obrotu jest określany w stopniach. Skalowanie. glscalef(glfloat x, Glfloat y, Glfloat z); Ściskanie i rozciąganie. Aleksander Dawid 2001-2012 rok 42

Przekształcenia w 3D (rzutowanie) Macierz tożsamościowa(jednostkowa). glmatrixmode(gl_modelview) Macierz modelu widoku. glloadidentity(); Ładuje macierz tożsamościową do bierzącej macierzy. Stos macierzy. Maksymalna wysokość stosu. glget(gl_max_model_view_stack_depth); glget(gl_max_projection_stack_depth); GL_STACK_OVERFLOW - przepełnienie stosu GL_STACK_UNDERFLOW - zdejmowanie ze stosu pustego. Aleksander Dawid 2001-2012 rok 43

Przekształcenia w 3D (rzutowanie) glpushmatrix(); Rotacje,translacje. glpopmatrix(); Własne macierze transformacji. Glfloat m[]={1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f} glmatrixmode(gl_modelview) glloadmatrix(m) // ładowanie macierzy jako bieżącej. glmatrixmode(gl_modelview) glmultmatrixf(m); // mnożenie macierzy Aleksander Dawid 2001-2012 rok 44

Kolory w OpenGL Dwie metody RGBA i color index. RGBA (red,green,blue,alpha) Color index wybrane kolory z większej palety glcolor4f(1.0f,1.0f,0.0f,1.0f); glcolori(12); Aleksander Dawid 2001-2012 rok 45

Światła w scenie (fotorealizm) (3) Światła: - otoczenia (ambient light) - rozproszone (diffuse) - odbłyski (specular) Światła w naszej scenie obliczamy załączając glenable(gl_lighting); Samo załączenie nic nie daje, trzeba jeszcze określić model oświetlenia. Bez tego nasz obiekt jest 2-wymiarowy. Najpierw określamy światło otoczenia. Glfloat ambient[] = {1.0f,1.0f,1.0f,1.0f} gllightmodelfv(gl_light_model_ambient,ambient); Aleksander Dawid 2001-2012 rok 46

Światła w scenie (fotorealizm) Właściwości materiałów. Nasze wielokąty muszą odbijać światło. Glfloat green[]={0.0f,0.75f,0.0f,1.0f); glmaterialfv(gl_front, GL_AMBIENT_AND_DIFFUSE, green); Przy załączonym oświetleniu tylko w ten sposób można określić kolor naszego trójkąta. glbegin(gl_triangles);... glend(); Aleksander Dawid 2001-2012 rok 47

Światła w scenie (fotorealizm) Generalnie teraz nie widać różnicy w naszej scenie. Faktyczna siła świateł tkwi w rozpraszaniu i odbłyskach. Właściwości materiału można określać dla przedniej lub tylnej ściany. GL_FRONT, GL_BACK, GL_FRONT_AND_BACK Inna metoda to śledzenie kolorów z użyciem glcolor jako funkcji określającej kolor. glenable(gl_color_material); glcolormaterial(gl_front, GL_AMBIENT_AND_DIFFUSE); Aleksander Dawid 2001-2012 rok 48

Światła w scenie (fotorealizm) Do bardziej realistycznych scen potrzebne nam są światła umiejscowione. Źródła te posiadają położenia, intensywności, kolory jak i kierunek padania. Aby biblioteka wiedziała jak mocno rozświetlić daną płaszczyznę potrzebuje aby został określony wektor normalny do płaszczyzny naszego wielokąta. Aleksander Dawid 2001-2012 rok 49

Wektor normalny Mając trzy punkty w przestrzeni możemy obliczyć wektory określające przestrzeń 2D V1 i V2 następnie produkt V1 x V2 da nam wektor prostopadły do naszej płaszczyzny. b a c Aleksander Dawid 2001-2012 rok 50

Wektor normalny void ReduceToUnit(float vector[3]) { float length; // Calculate the length of the vector length = (float)sqrt((vector[0]*vector[0]) + (vector[1]*vector[1]) + (vector[2]*vector[2])); if(length == 0.0f) length = 1.0f; vector[0] /= length; vector[1] /= length; vector[2] /= length; } Aleksander Dawid 2001-2012 rok 51

Wektor normalny void NormV(GLfloat va[3], GLfloat vb[3], GLfloat vc[3], GLfloat out[3]) { float v1[3],v2[3]; static const int x = 0, y=1, z=2; v1[x] = vb[x] - va[x]; v1[y] = vb[y] - va[y]; v1[z] = vb[z] - va[z]; v2[x] = vc[x] - va[x]; v2[y] = vc[y] - va[y]; v2[z] = vc[z] - va[z]; out[x] = v1[y]*v2[z] - v1[z]*v2[y]; out[y] = v1[z]*v2[x] - v1[x]*v2[z]; out[z] = v1[x]*v2[y] - v1[y]*v2[x]; ReduceToUnit(out); } Aleksander Dawid 2001-2012 rok 52

Wektor normalny OpenGL Kąt obserwatora - kąt między wektorem normalnym a promieniem padania światła zrzutowany na płaszczyznę widzenia Kąt obserwatora jest miarą jasności danego wielokąta Glfloat va[3] = {40.0f,0.0f,0.0f}; Glfloat vb[3] = {0.0f,60.0f,0.0f}; Glfloat vc[3] = {-40.0f,0.0f,0.0f}; normlight[3]; NormV(va, vb, vc, normlight); glbegin(gl_trangle); glnormal3fv(&normlight); glvertex3fv(&va); glvertex3fv(&vb); glvertex3fv(&vc); glend(); Aleksander Dawid 2001-2012 rok 53

Światła w scenie (fotorealizm) Przygotowanie źródła światła. Glfloat ambient[]={0.3,0.3,0.3,1.0f} Glfloat diffuse[]={0.7,0.7,0.7,1.0} gllightfv(gl_light0,gl_ambient,ambient); gllightfv(gl_light0,gl_diffuse,diffuse); Glfloat lpos[]={-50.0f,50.0f,100.0f,1.0f} gllightfv(gl_light0,gl_position,lpos); glenable(gl_light0); Do ustalenia koloru możemy także użyć funkcji glrgb(0,255,0); Aleksander Dawid 2001-2012 rok 54

Światła w scenie (fotorealizm) Przygotowanie źródła światła. Glfloat specular[]={1.0,1.0,1.0,1.0f} gllightfv(gl_light0,gl_specular,specular); Ostatnia linia definiuje światło jasno białe dla odbłysków. STOPIEŃ POŁYSKLIWOŚCI. glmateriali(gl_front,gl_shininess,128); Określa jak mała i skupiona będzie plama połysku. Aleksander Dawid 2001-2012 rok 55

Światła w scenie (fotorealizm) Domyślnie światło rozchodzi się w każdym kierunku. W celu przeniesienia światła do nieskończoności trzeba w ostatnim elemencie dać wartość zero. Światło punktowe załączamy przez gllightf(gl_light0,gl_spot_cutof,60.0f); gllightf(gl_light0,gl_spot_exponent,100.0f); glpushattrib(gl_lighting_bit); Instrukcja zachowuje stan oświetlenia. glpopattrib(); Przywraca pierwotny stan oświetlenia. Aleksander Dawid 2001-2012 rok 56

Cienie (fotorealizm) Tworzenie cieni nie jest zaimplementowane w OpenGL bezpośrednio. Cienie można stworzyć programowo na kilka sposobów. Na podstawie równania płaszczyzny i położenia światła tworzy się macierz rzutu cienia. Macierz ta jest zwykłą macierzą rzutowania perspektywicznego, z tą różnicą, że punktem położenia obserwatora jest tutaj położenie źródła światła. Jeśli tę macierz będziemy mnożyć przez macierz widoku modelu, to obiekty będą spłaszczane na tę płaszczyznę Aleksander Dawid 2001-2012 rok 57

Cienie (fotorealizm) // Procedura tworząca macierz rzutu cienia. void MakeShadowMatrix(GLfloat points[3][3], GLfloat lightpos[4], GLfloat destmat[4][4]) { GLfloat planecoeff[4]; GLfloat dot; // Znalezienie współczynników równania płaszczyzny // Wyszukanie trzech pierwszych współczynników tak samo // jak przy znajdowaniu normalnej calcnormal(points,planecoeff); // Znalezienie ostatniego współczynnika przez zastępowanie wstecz planecoeff[3] = - ( (planecoeff[0]*points[2][0]) + (planecoeff[1]*points[2][1]) + (planecoeff[2]*points[2][2])); Aleksander Dawid 2001-2012 rok 58

Cienie (fotorealizm) // Iloczyn skalarny płaszczyzny i położenia światła dot = planecoeff[0] * lightpos[0] + planecoeff[1] * lightpos[1] + planecoeff[2] * lightpos[2] + planecoeff[3] * lightpos[3]; // A teraz rzutowanie // Pierwsza kolumna destmat[0][0] = dot - lightpos[0] * planecoeff[0]; destmat[1][0] = 0.0f - lightpos[0] * planecoeff[1]; destmat[2][0] = 0.0f - lightpos[0] * planecoeff[2]; destmat[3][0] = 0.0f - lightpos[0] * planecoeff[3]; // Druga kolumna destmat[0][1] = 0.0f - lightpos[1] * planecoeff[0]; destmat[1][1] = dot - lightpos[1] * planecoeff[1]; destmat[2][1] = 0.0f - lightpos[1] * planecoeff[2]; destmat[3][1] = 0.0f - lightpos[1] * planecoeff[3]; Aleksander Dawid 2001-2012 rok 59

Cienie (fotorealizm) // Trzecia kolumna destmat[0][2] = 0.0f - lightpos[2] * planecoeff[0]; destmat[1][2] = 0.0f - lightpos[2] * planecoeff[1]; destmat[2][2] = dot - lightpos[2] * planecoeff[2]; destmat[3][2] = 0.0f - lightpos[2] * planecoeff[3]; } // Czwarta kolumna destmat[0][3] = 0.0f - lightpos[3] * planecoeff[0]; destmat[1][3] = 0.0f - lightpos[3] * planecoeff[1]; destmat[2][3] = 0.0f - lightpos[3] * planecoeff[2]; destmat[3][3] = dot - lightpos[3] * planecoeff[3]; Program shadows.c Aleksander Dawid 2001-2012 rok 60

Listy wyświetalania Listy wyświetlania przyspieszają wykonywanie programu OpenGL w przypadku dużej liczby wielokątów. PROCEDURA glnewlist(1, GL_COMPILE);... Kod OpenGL glendlist(); Następnie wywołanie tak przygotowanej listy wygląda następująco glcalllist(1); Zamiast 1 można zasosować dowolny identyfikator Gluint list Aleksander Dawid 2001-2012 rok 61

Grafika rastrowa BITMAPY. Obrazki 2 - kolorowe. Kolor 0 - przezroczysty 1 - bieżący. Do rysowania bitmap służy funkcja glbitmap glbitmap(glsizei width,glsizei height, Glfloat xorig,glfloat yorig,glfloat xmove, Glfloat ymove,const Glubyte *bits) xorig,yorig - położenie środka xmove,ymove - przesunięcie w bitmapie. Do ustalenia pozycji obrazka na naszym oknie służy. glrasterpos2i(x,y); Aleksander Dawid 2001-2012 rok 62

Grafika rastrowa CZCIONKI BITMAPOWE. Aby w OpenGL wyświetlić jakieś teksty na ekranie trzeba przygotować odpowiedni zestaw czcionek. Gluint base; HDC hdc; base=glgenlists(96); wglusefontbitmaps(hdc,32,96,base); Tworzy 96 bitmap znaków poczynając od kodu 32 gllistbase(font-32); glcalllists(strlen(s), GL_UNSIGNED_BYTE, s); Aleksander Dawid 2001-2012 rok 63

Grafika rastrowa Funkcja gllistbase ustawia wartość bazową list wyświetlania. glcalllists - wyświetla nam nasze czcionki wg. zadanego tekstu. Czcionkę możemy ustawić funkcjami Win32 font=createfont(...) SelectObject(hdc,font); Aleksander Dawid 2001-2012 rok 64

Grafika rastrowa. PIXMAPY Obrazy zawierające więcej niż 2 kolory nazywamy pixmapami. Do rysowania pixmap służy funkcja gldrawpixels(glsizei width, Glsizei height, Glenum format, Glenum type, Glvoid *pixels) format GL_COLOR_INDEX GL_RGB GL_LUMINANCE type GL_BYTE GL_UNSIGNED_BYTE GL_BITMAP Aleksander Dawid 2001-2012 rok 65

Grafika rastrowa REMAPOWANIE KOLORÓW glpixeltransfer(gl_red_scale, 1.1); glpixeltransfer(gl_green_scale, 1.1); glpixeltransfer(gl_blue_scale, 1.1); Kod rozjaśnia obraz RGB o 10% SKALOWANIE PIXMAP glpixelzoom(1.0,1.0);brak skalowania glpixelzoom(-1.0,1.0);odbicie lustrzane w poziomie glpixelzoom(0.2,0.2);zmniejszenie obrazka Aleksander Dawid 2001-2012 rok 66

Grafika rastrowa WYKRAWANIE OBSZARÓW glpixelstore(gl_unpack_row_lenght, 640); glpixelstore(gl_unpack_skip_pixels, 100); glpixelstore(gl_unpack_skip_rows, 100); gldrawpixels(300,300,gl_rgb,gl_unsigned_byte,bi tmapbits); ODCZYTYWANIE PIXMAP Z EKRANU glreadpixels(glint x,glint y,glsizei width Glsizei height, Glenum format, Glenum type, const Glvoid *pixels); Aleksander Dawid 2001-2012 rok 67

Mapowanie tekstur Nakładanie obrazów na wielokąty w scenie. Akceleratory 3D same mapują tekstury. Definiowanie textur 1D glteximage1d(glenum target,glint level,glint components,glsizei width, Glint border, Glenum format, Glenum type, const Glvoid *pixels); target - określa jaka tekstura powinna być zdefiniowana (GL_TEXTURE_1D) level - poziom szczegółów obrazu zwykle 0 jak nie ma mipmapy. Components - okresla ilosc wartosci koloru dla jednego pixela RGB=3, RGBA=4 Aleksander Dawid 2001-2012 rok 68

Mapowanie tekstur Width - długość ciągu pixeli musi stanowić potęgę 2. border - pixle ramki format - określa w jakim formacie zapisane są kolory (GL_COLOR_INDEX, GL_RGB, GL_RGBA, GL_LUMINANCE); FILTRY POWIĘKSZENIA I POMNIEJSZENIA. gltexparameteri(gl_texture_1d, GL_TEXTURE_MIN_FILTER,GL_LNEAR); gltexparameteri(gl_texture_1d,gl_texture_mag_filter,gl_lnear); GL_NEAREST,GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR - liniowo interpolowana mipmapa GL_LINEAR_MIPMAP_LINEAR - liniowo interpolacja interpolowanych mipmap. GL_NEAREST - najlepsza wydajnosc. Aleksander Dawid 2001-2012 rok 69

Mapowanie tekstur Definiowanie textur 2D glteximage2d(glenum target,glint level, Glint components, Glsizei width, Glsizei height, Glint border, Glenum format, Glenum type, const Glvoid *pixels) Dodany jedynie height czyli wysokość mapowanego obrazka. width i height muszą być rozmiaru potęg liczby 2 2,4,8,16,32,64,128,256,512,1024 Aleksander Dawid 2001-2012 rok 70

Mapowanie tekstur Rysowanie wielokątów z nałożoną teksturą. Teksturowanie trzeba załączyć glenable(gl_texture_nd); gltexenvi(gl_texture_env,gl_texture_env_mode, GL_DECAL); Ustawienie teksturowania w tryb kafelków. GL_MODULATE - piksele tekstury filtrują kolory istniejących pikseli na ekranie GL_DECAL GL_BLEND - łączenie ze stałym kolorem. Symulacja chmur. Aleksander Dawid 2001-2012 rok 71

Mapowanie tekstur MIPMAPY Pozwalają zastosować zmienny poziom szczegółów w zależności od odległości od obserwatora. Użycie mniejszych obrazków zwiększa wiarygodność sceny jak i wydajność kodu. Wprowadzamy mipmapy przez funkcje glteximagend podając level i odpowiadającą mu mapę. glteximage2d(gl_texture_2d,0,3,128,128,gl_rgb,gl_unsigned_byte, imagebits0); glteximage2d(gl_texture_2d,1,3,128,128,gl_rgb,gl_unsigned_byte, imagebits1); GL_LINEAR_MIPMAP_LINEAR; Aleksander Dawid 2001-2012 rok 72

Przykładowy Program mapowanie tekstur GLvoid PolygonTex(GLvoid) { GLfloat s=1.0f; glenable(gl_texture_2d); gltexenvi(gl_texture_env, GL_TEXTURE_ENV_MODE, GL_DECAL); glcalllist(walltexture); } glbegin(gl_polygon); gltexcoord2f(0.0, 0.0); glvertex3f(-4.0,-1.0,1.0); gltexcoord2f(s, 0.0); glvertex3f(4.0,-1.0,1.0); gltexcoord2f(s, s); glvertex3f(4.0,-1.0,-5.0); gltexcoord2f(0.0, s); glvertex3f(-4.0,-1.0,-5.0); glend(); Aleksander Dawid 2001-2012 rok 73

Kwadryki (4) GLU32.DLL biblioteka utility OpenGL W niej zdefiniowane są proste kształty 3D takie jak cylindry,sfery,walce,dyski,powierzchnie. GLUquadricObj *quadobj; Struktura danych w której przechowywane są informacje na temat wierzchołków, normalnych, współrzędnych tekstur, sposobu łączenia wierzchołków i wiele innych. Dostęp do tych parametrów zapewniają odpowiednie funkcje. quadobj = glunewquadric(); Instrukcja tworzy nowy obiekt quadobj gludeletequadric (quadobj); Instrukcja niszczy obiekt quadobj i zwalnia pamięć gluquadriccallback (quadobj, GLenum which, void (*fn)()); fn funkcja kontrolna wywoływana w przypadku błędów. Aleksander Dawid 2001-2012 rok 74

Kwadryki gluquadricorientation(quadobj,glu_outside); Kontrola kierunku wektorów normalnych GLU_OUTSIDE na zewnątrz figury GLU_INSIDE do wnętrza figury gluquadricnormals (quadobj, GLU_SMOOTH); Definiuje wektory normalne. GLU_NONE - wartość domyślna, brak wektorów normalnych, stosowana przy braku oświetlenia. GLU_FLAT generowanie wektorów normalnych dla każdej powierzchni, stosowane w przypadku cieniowania. GLU_SMOOTH generowani wektorów normalnych dla każdego wierzchołka, najlepsza jakość przy oświetleniu. Aleksander Dawid 2001-2012 rok 75

Kwadryki gluquadricdrawstyle (quadobj, GLU_LINE); Ustawia styl renderowania obiektów. GLU_POINT wierzchołki przedstawiane jako punkty. GLU_LINE wierzchołki połączone liniami, model szkieletowy. GLU_SILHOUETTE wierzchołki połączone liniami, stosowane w dyskach. GLU_FILL wypełnione wielokąty, rysowane zgodnie z kierunkiem wskazywanym przez wektory normalne. gluquadrictexture (quadobj, GLU_TRUE); Funkcja odpowiedzialna za generowanie współrzędnych tekstury GLU_FALSE Wartość domyślna, brak generowania współrzędnych tekstury. GLU_TRUE Załączone generowanie współrzędnych tekstury, zależne od typu obiekty kwadryki. Aleksander Dawid 2001-2012 rok 76

Kwadryki - prymitywy glusphere(quadobj, radius, gridalfa, gridgama); radius - promień sfery gridalfa - rozdzielczość elementów pozioma gridgama - rozdzielczość elementów pionowa glucylinder(quadobj,rbase,rtop,height,slices,stacks); Rbase - promień podstawy Rtop - promień wierzchołka Height - wyskość slices,stacks - określają z ilu elementów składa się obiekt. gludisk(quadobj,rinner,router,slices,loops); Rinner - promień wewnętrznego dysku. Router - promień zewnętrznego dysku. slices,loops - określają z ilu elementów składa się obiekt. Aleksander Dawid 2001-2012 rok 77

Kwadryki - prymitywy glupartialdisk(quadobj,rinner,router,slices,loops,starta ngle, sweepangle); Rinner - promień wewnętrznego dysku Router - promień zewnętrznego dysku slices,loops - określają z ilu elementów składa się obiekt startangle kąt startowy sweepangle kąt częściowego dysku Aleksander Dawid 2001-2012 rok 78

Kwadryki - program GLvoid RenderQuadrics() { glenable(gl_lighting); glshademodel (GL_SMOOTH); gltranslatef(-1.0, -1.0, 0.0); glcalllist(startlist); glshademodel (GL_FLAT); gltranslatef(0.0, 2.0, 0.0); glpushmatrix(); glrotatef(300.0, 1.0, 0.0, 0.0); glcalllist(startlist+1); glpopmatrix(); gldisable(gl_lighting); glcolor3f(0.0, 1.0, 1.0); gltranslatef(2.0, -2.0, 0.0); glcalllist(startlist+2); } glcolor3f(1.0, 1.0, 0.0); gltranslatef(0.0, 2.0, 0.0); glcalllist(startlist+3); Aleksander Dawid 2001-2012 rok 79

Przezroczystość Przezroczystość (BLENDING). Polega na łączeniu kolorów czyli kontrolowaniu wartości RGBA poszczególnych pixeli. Wartość A odpowiada bezpośrednio za blending. Kolor źródłowy(r s,g s,b s,a s ) Kolor docelowy(r d,g d,b d,a d ) Czynniki przezroczystości źródła (S r,s g,s b,s a ) Czynniki przezroczystości docelowy (D r,d g,d b,d a ) Równanie przezroczystości (R s S r +R d D r, G s S g +G d D g, B s S b +B d D b, A s S a +A d D a ) glenable(gl_blend). Załączenie łączenia kolorów bieżącego z kolorem zeskładowanym w buforze ramki. gldisable(gl_blend) - wyłączenie obliczeń kolorów. Aleksander Dawid 2001-2012 rok 80

Przezroczystość glblendfunc(gl_src_alpha,gl_one_minus_src_alpha); Parametry określają sposoby łączenia kolorów źródłowego i docelowego. Dla tych ustawień kolor alpha będzie określał przezroczystość. GL_ZERO źródło lub przeznaczenie (0, 0, 0, 0) GL_ONE źródło lub przeznaczenie (1, 1, 1, 1) GL_DST_COLOR źródło (Rd, Gd, Bd, Ad) GL_SRC_COLOR przeznaczenie (Rs, Gs, Bs, As) GL_ONE_MINUS_DST_COLOR źródło (1, 1, 1, 1)-(Rd, Gd, Bd, Ad) GL_ONE_MINUS_SRC_COLOR przeznaczenie (1, 1, 1, 1)-(Rs, Gs, Bs, As) GL_SRC_ALPHA źródło lub przeznaczenie (As, As, As, As) GL_ONE_MINUS_SRC_ALPHA źródło lub przeznaczenie (1, 1, 1, 1)-(As, As, As, As) GL_DST_ALPHA źródło lub przeznaczenie (Ad, Ad, Ad, Ad) GL_ONE_MINUS_DST_ALPHA źródło lub przeznaczenie (1, 1, 1, 1)-(Ad, Ad, Ad, Ad) GL_SRC_ALPHA_SATURATE źródło (f, f, f, 1); f=min(as, 1-Ad) Aleksander Dawid 2001-2012 rok 81

Przezroczystość GLvoid drawscene(glvoid) { glclearcolor( 0.0F, 0.0F, 0.0F, 0.0F); glcleardepth( 1.0 ); glclear( GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT); if(x>2.0)x=0; x+=0.01; glpushmatrix(); drawrighttriangle(); glpopmatrix(); glpushmatrix(); gltranslatef(x,0.0f,0.0f); drawlefttriangle(); glpopmatrix(); } SWAPBUFFERS; GLvoid initializegl(glsizei width, GLsizei height) { glenable (GL_BLEND); glblendfunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glshademodel (GL_FLAT); glclearcolor( 0.0f, 0.0f, 0.0f, 0.0f); } Aleksander Dawid 2001-2012 rok 82

Antialiasing Wygładzanie krawędzi krzywych Problem pojawia się gdy krzywe rysowane są pod dużym kątem, wtedy pojawiają się na krzywej schodki. Obraz bez antialiasingu Obraz z antialiasingiem Wygładzanie polega na dodaniu dodatkowych krzywych pokrywających. Realizacja tego zadania zależy od sterowników karty graficznej Aleksander Dawid 2001-2012 rok 83

Antialiasing Jakość krzywych glhint(glenum target, GLenum hint) Hint: GL_FASTEST, GL_NICEST, GL_DONT_CARE Parametr GL_POINT_SMOOTH_HINT, GL_LINE_SMOOTH_HINT, GL_POLYGON_SMOOTH_HINT Znaczenie Określa jakość próbkowania dla punktów,linii, lub wielokątów podczas operacji antialiasingu GL_FOG_HINT GL_PERSPECTIVE_CORRECTION_ HINT Określa czy obliczenia dla mgły maja być wykonane dla piksla (GL_NICEST) lub dla wierzchołka (GL_FASTEST) Określa jakość danego koloru i interpolacji współrzędnych tekstury. Aleksander Dawid 2001-2012 rok 84

Mgła Mgła (FOG). Dodanie efektu atmosferycznego czyli zależnego od głębokości cieniowania każdego elementu sceny polega na wymieszaniu pewnego koloru z każdym wierzchołkiem lub obiektem tekstury. glenable(gl_fog); Wybieramy rodzaj mgły. glfogi(gl_fog_mode, GL_LINEAR); GL_EXP,GL_EXP2 Wybieramy kolor mgły. GLfloat fogcolor[4] = {0.7F, 0.8F, 1.0F, 1.0F}; glfogfv (GL_FOG_COLOR, fogcolor); Aleksander Dawid 2001-2012 rok 85

Mgła Mgła (FOG). Symuluje efekty atmosferyczne takie jak mgły, zadymienie, zanieczyszczenie środowiska. Pozwala obiektom dalekim płynnie znikać. Możemy kontrolować gęstość mgły jak i jej kolor. glfogf (GL_FOG_DENSITY, 0.005); glfogi(gl_fog_mode, GL_EXP); F=e -(density.z) (GL_EXP) F=e -(density.z)^2) (GL_EXP2) F=(end-z)/(end-start)(GL_LINEAR) glhint (GL_FOG_HINT, GL_DONT_CARE); Aleksander Dawid 2001-2012 rok 86

Mgła GLfloat fogcolor[4] = {0.5, 0.5, 0.5, 1.0}; glfogi (GL_FOG_MODE, GL_EXP); glfogfv (GL_FOG_COLOR, fogcolor); glfogf (GL_FOG_DENSITY, 0.065f); glhint (GL_FOG_HINT, GL_DONT_CARE); glfogf (GL_FOG_START, 1.0); glfogf (GL_FOG_END, 5.0); Aleksander Dawid 2001-2012 rok 87

Krzywe glmap1f(glenum target,glfloat u1,glfloat u2, GLint stride,glint order,const GLfloat *points) Funkcja rysuje krzywe Beziera na podstawie punktów kontrolnych. Target - typ. współrzędnych GL_MAP1_VERTEX_3 - wierzchołki (x, y, z). GL_MAP1_COLOR_4 - kolory punktów w postaci (r, g, b, a). GL_MAP1_TEXTURE_COORD_2 - współrzędne w obszarze tekstury (s, t). GL_MAP1_NORMAL - współrzędne wektora normalnego (nx, ny, nz). u1,u2 to dziedzina funkcji Stride - oznacza liczbę współrzędnych składających się na każdy punkt kontrolny order - liczba punktów kontrolnych Aleksander Dawid 2001-2012 rok 88

Krzywe glenable(target); void glmapgrid1f(glint n, GLfloat u1, GLfloat u2) N określa ilość punktów krzywej do obiczeń, u1,u2 dziedzina void glevalmesh1(glenum mode, GLint p1, GLint p2) mode - GL_ POINTS, GL_LINE p1 i p2 oznaczają numery próbek, od których zaczynamy i na których kończymy obliczenia. Aleksander Dawid 2001-2012 rok 89

Krzywe float fctrlpointsarray[4][3]= { {(0.0f/3.0f)*4.0f-2.0f,(1.0f)*4.0f-2.0f,0.0f}, {(1.0f/3.0f)*4.0f-2.0f,(3.0f/4.0f)*4.0f-2.0f,0.0f}, {(2.0f/3.0f)*4.0f-2.0f,(3.0f/5.0f)*4.0f-2.0f,0.0f}, {(3.0f/3.0f)*4.0f-2.0f,(1.0f/2.0f)*4.0f-2.0f,0.0f} }; void Init(void) { glclearcolor(0.0,0.0,0.0,0.0); glmap1f(gl_map1_vertex_3,0.0,1.0,3,4,&fctrlpointsarray[0][0]); glenable(gl_map1_vertex_3); glmapgrid1f(100,0.0,1.0); } void CALLBACK Display(void) { glclear(gl_color_buffer_bit); glcolor3f(1.0,1.0,1.0); glevalmesh1(gl_line,0,100); glpointsize(3.0); glcolor3f(1.0,0.0,0.0); glbegin(gl_points); for (i=0;i<4;i++) glvertex3fv(&fctrlpointsarray[i][0]); glend(); glflush(); } Aleksander Dawid 2001-2012 rok 90

Powierzchnie void glmap2f(glenum target,glfloat u1,glfloat u2,glint ustride,glint uorder,glfloat v1, GLfloat v2,glint vstride,glint vorder,const GLfloat *points); MAP1 -> MAP2 void glmapgrid2f(glint nu, Glfloat u1, Glfloat u2, GLint nv, Glfloat v1, Glfloat v2) void glevalmesh2(glenum mode, GLint i1, GLint i2, GLint j1, GLint j2). Aleksander Dawid 2001-2012 rok 91

Powierzchnie i Krzywe Przykłady f(x, y) = 1/[(x + 1) (y + 1)] glmap2f(gl_map2_vertex_3,0.0,1.0,3,4,0.0,1.0,1 2,4,&fCtrlPointsArray[0][0][0]); glmap2f(gl_map2_texture_coord_2,0.0,1.0,2,2,0. 0,1.0,4,2,&fTexCtrlPointsArray[0][0][0]); glenable(gl_map2_vertex_3); glenable(gl_map2_texture_coord_2); glmapgrid2f(100,0.0,1.0,100,0.0,1.0); Aleksander Dawid 2001-2012 rok 92

Bufor głębokości Działanie bufora głębokości polega na przechowywaniu współrzędnej z dla każdego piksela obrazu. Podczas renderingu obliczana jest wartość współrzędnej z piksela obrazu i porównywana jest z wartością bufora głębokości. W ten sposób stwierdzane jest przesłanianie obiektów namalowanych wcześniej. Standardowo OpenGL nie wykonuje operacji na buforze głębokości Włączenie bufora głębokości glenable(gl_depth_test) Wyłączenie zapisu do bufora głębokości gldepthmask(glboolean flag) flag GL_TRUE, GL_FALSE Aleksander Dawid 2001-2012 rok 93

Bufor głębokości Kontrola sposobu sprawdzania bufora głębokości gldepthfunc(glenum func) Wartości func GL_NEVER - wartość testu zawsze negatywna, GL_LESS - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest mniejsza od wartości znajdującej się w buforze; wartość domyślna, GL_EQUAL - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest równa wartości znajdującej się w buforze, GL_LEQUAL - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest mniejsza lub równa wartości znajdującej się w buforze, GL_GREATER - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest większa od wartości znajdującej się w buforze, GL_NOTEQUAL - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest różna od wartości znajdującej się w buforze, GL_GEQUAL - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest większa lub równa wartości znajdującej się w buforze, GL_ALWAYS - wartość testu zawsze pozytywna. Aleksander Dawid 2001-2012 rok 94

Bufor głębokości Czyszczenie bufora głębokości Przez rozpoczęciem rysowania elementów sceny 3D konieczne jest wyczyszczenie zawartości bufora głębokości. Wymaga to dodania stałej GL_DEPTH_BUFFER_BIT przy wywołaniu funkcji glclear. glcleardepth( GLclampd depth ) Standardowo bufor głębokości zawiera liczby z przedziału [0, 1] i jest czyszczony liczbą 1 Biblioteka OpenGL umożliwia zmianę tego przedziału poprzez użycie funkcji: gldepthrange( GLclampd znear, GLclampd zfar ) Aleksander Dawid 2001-2012 rok 95

Bufor głębokości Przesunięcie wartości głębi W wersji 1.1 biblioteki OpenGL, a wcześniej w rozszerzeniu EXT polygon offset, wprowadzono mechanizm pozwalający na przesuwanie wartości głębi pikseli przy rysowaniu wielokątów. Przesunięcie wyliczane jest na podstawie wzoru: (m * factor) + (r * units) którego współczynnik m oznacza maksymalne nachylenie głębokości wielokąta (obliczenia wykonuje OpenGL), a współczynnik r jest zależną od implementacji najmniejszą różnicą wartości przechowywanych w buforze głębokości. Określenie wartości współczynników skalowania factor i units wymaga wywołania funkcji: glpolygonoffset( GLfloat factor, GLfloat units ) Przesuwanie wartości głębi jest domyślnie wyłączone. Włączenie tego mechanizmu wymaga wywołania funkcji glenable z jednym z poniższych parametrów: GL_POLYGON_OFFSET_POINT - przesuwanie wartości głębi, gdy rysowane są tylko wierzchołki wielokątów, GL_POLYGON_OFFSET_LINE - przesuwanie wartości głębi, gdy rysowane są tylko krawędzie wielokątów, GL_POLYGON_OFFSET_FILL - przesuwanie wartości głębi, gdy rysowane są wypełnione wielokąty. Aleksander Dawid 2001-2012 rok 96

Bufor szablonowy (5) Stencil buffer Bufor dodatkowy (konfigurowalny), podobny do bufora głębokości. Składowany w nim jest szablon kolorów jako filtr. Bufor ten określa, które piksele ekranu mają ulegać zmianie, a które nie. Wartości w buforze szablonu przechowywane są dla każdego piksela. Ilość bitów na 1 piksel wacha się między 1 a 8. Przy 8bit rozdzielczości możemy nałożyć 256 warunków na wyświetlanie pikseli. Zastosowania Cienie (shadows) Lustra (mirrors) Filtry Aleksander Dawid 2001-2012 rok 97

Bufor szablonowy Załączenie/Wyłączenie bufora glenable(gl_stencil_test); gldisable(gl_stencil_test); Czyszczenie bufora szablonowego glclear(gl_stencil_buffer_bit); Domyślnie bufor szablonowy wypełniany jest zerami, ale można to zmienić przy pomocy funkcji. glclearstancil(glint s);, gdzie s jest dowolna liczbą całkowitą Aleksander Dawid 2001-2012 rok 98

Bufor szablonowy Sterowanie buforem szablonowym glstencilfunc( GLenum func, GLint ref, GLuint mask ) Dla parametru func mamy te same możliwości co dla bufora głębokości GL_NEVER - wartość testu zawsze negatywna, GL_LESS - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest mniejsza od wartości znajdującej się w buforze; wartość domyślna, GL_EQUAL - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest równa wartości znajdującej się w buforze, GL_LEQUAL - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest mniejsza lub równa wartości znajdującej się w buforze, GL_GREATER - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest większa od wartości znajdującej się w buforze, GL_NOTEQUAL - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest różna od wartości znajdującej się w buforze, GL_GEQUAL - wartość testu pozytywna jeżeli testowana wartość współrzędnej z jest większa lub równa wartości znajdującej się w buforze, GL_ALWAYS - wartość testu zawsze pozytywna. Aleksander Dawid 2001-2012 rok 99

Bufor szablonowy Parametr ref Parametr ref określa wartość referencyjną używaną w teście bufora szablonowego. Wartość ta jest zawsze obcinana do przedziału [0, 2n 1], gdzie n jest ilością bitów bufora szablonu. Parametr mask Określa maskę bitową dla których bitów wykonywany jest test porównania wartości referencyjnej z wartościami zeskładowanymi w buforze szablonu. Domyślna wartość maski bitowej dla bufora szablonu wynosi 1. Ustawienie te można zmienić przy pomocy funkcji glstencilmask(uint mask) Aleksander Dawid 2001-2012 rok 100

Funkcja sterująca buforem Bufor szablonowy glstencilop(glenum sfail,glenum dpfail,glenum dppass) sfail, określa reakcję na negatywny wynik testu bufora szablonu dpfail, pozytywny wynik testu bufora szablonu, negatywny bufora głębokości dppass, pozytywny szablonu i głębokości Domyślna wartość dla wszystkich tych przypadków to GL_KEEP GL_KEEP - wartość bufora szablonowego nie jest zmieniana, GL_ZERO - wartość bufora szablonowego jest zerowana, GL_REPLACE - wartość bufora szablonowego jest zamieniana wartością referencyjną określoną w parametrze ref funkcji glstencilfunc, GL_INCR - wartość bufora szablonowego jest zwiększana o 1; w przypadku wystąpienia nadmiaru rezultat przyjmuje maksymalną wartość obsługiwaną przez bufor szablonowy, GL_DECR - wartość bufora szablonowego jest zmniejszana o 1; w przypadku wystąpienia niedomiaru rezultat przyjmuje wartość 0, GL_INVERT - wartość bufora szablonowego jest negowana, GL_DECR_WRAP - wartość bufora szablonowego jest zmniejszana o 1; w przypadku wystąpienia niedomiaru rezultat przyjmuje maksymalną wartość obsługiwaną przez bufor szablonowy, GL_INCR_WRAP - wartość bufora szablonowego jest zwiększana o 1; w przypadku wystąpienia nadmiaru rezultat przyjmuje wartość 0. Aleksander Dawid 2001-2012 rok 101

Bufor szablonowy W OpenGL 2.0 wprowadzono wersje tych funkcji osobne dla przedniej GL_FRONT i tylnej GL_BACK wielokąta. 0 0 1 2 GL_FRONT 2 1 GL_BACK glstencilfuncseparate(enum face,enum func,int ref,uint mask ) glstencilopseparate(enum face,enum sfail,enum dpfail,enum dppass ) glstencilmaskseparate(enum face,uint mask) Aleksander Dawid 2001-2012 rok 102

Bufor szablonowy Odbicie lustrzane gldisable(gl_stencil_test); glenable(gl_stencil_test); Aleksander Dawid 2001-2012 rok 103

Bufor akumulacyjny Przechowuje informacje RGBA dla koloru, w trybie kolor indeks jest niedostępny. Zadania Łączenie kilku obrazów w celu uzyskania pożądanego efektu końcowego. Zastosowanie Efekt rozmycia podczas ruchu (ang. motion blur) Głębia ostrości (ang. depth of field) antyaliasing pełnoekranowy (ang. FSAA - Full Scene Anti Aliasing) miękkie cienie (ang. soft shadows) Aleksander Dawid 2001-2012 rok 104

Sterowanie buforem Bufor akumulacyjny glaccum(glenum op,glfloat value) op określa rodzaj operacji wykonywanej na buforze value parametr operacji (R a,g a,b a,a a ) wektor bufora akumulacji (R c,g c,b c,a c ) wektor bufora kolorów Dostępne operacje op algebraiczne na buforze akumulacji GL_ACCUM R a = R a + value R c G a = G a + value G c B a = B a + value B c A a = A a + value A c Aleksander Dawid 2001-2012 rok 105

Bufor akumulacyjny GL_LOAD GL_RETURN GL_MULT GL_ADD R a = value R c G a = value G c B a = value B c A a = value A c R c = value R a G c = value G a B c = value B a A c = value A a R a = value R a G a = value G a B a = value B a A a = value A a R a = R a + value G a = G a + value B a = B a + value A a = A a + value Aleksander Dawid 2001-2012 rok 106

Bufor akumulacyjny Czyszczenie bufora akumlacyjnego glclear(gl_accum_buffer_bit) Domyślna wartość wypełnienia to wektor zerowy (0,0,0,0) Wartość tę można zmienić przez funkcję glclearaccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) Składowe kolorów w razie potrzeby obcinane są do przedziału [ 1, 1] Aleksander Dawid 2001-2012 rok 107

Bufor akumulacyjny Rozmycie w ruchu // dodanie przeskalowanych wartości z bufora kolorów do bufora akumulacynego glaccum( GL_ACCUM, 0.1f ); // kopiowanie wartości z bufora akumulacyjnego do bufora kolorów glaccum( GL_RETURN, 1.0f ); // załadowanie przeskalowanych wartości z bufora kolorów do bufora akumulacyjnego glaccum( GL_LOAD, 0.9f ); Aleksander Dawid 2001-2012 rok 108

GL Shading Language (GLSL) Wprowadzenie do programowania shaderów Aleksander Dawid 2001-2012 rok 109

GL Shading Language (GLSL) Język shaderów wprowadzony został w celu oprogramowania tych elementów OpenGL, które miały ustaloną funkcjonalność. Dotyczy to przetwarzania wierzchołków i fragmentów. Fragment jest wynikiem rasteryzacji prymitywów składających się z wierzchołków kolorów i tekstur. Przetwarzanie fragmentów dotyczy takich operacji jak przycinanie, test alfa, test głębokości, test szablonu, mieszanie kolorów, mapowania tekstur i wiele innych. Shader niezależnie kompilowalna jednostka obliczeniowa Program to zestaw shaderów, skompilowanych i połączonych razem Aleksander Dawid 2001-2012 rok 110

GL Shading Language (GLSL) Połączenia wierzchołków Wierzchołki Transformacja wierzchołków (vertex shader) Przetworzone wierzchołki Składanie prymitywów i rasteryzacja Położenia pikseli Fragmenty Odświeżenie pikseli Rasteryzacja Pokolorowane fragmenty Teksturowanie i kolorowanie fragmentów (pixel shader) Potok przetwarzania grafiki komputerowej Aleksander Dawid 2001-2016 rok 111

GL Shading Language (GLSL) Procesor wierzchołków Na wejściu: położenia, kolor, normalne, współrzędne tekstury Ustalona funkcjonalność Transformacje pozycji wierzchołka Oświetlenie dla wierzchołka Generowanie i przekształcanie współrzędnych tekstur Składanie prymitywów i rasteryzacja Na wejściu: informacja o wierzchołkach i sposobie ich połączenia Na tym etapie wykonywane są również obliczenia związane z obcinanie względem bryły widoku oraz usuwane są niewidoczne powierzchnie Na wyjściu: matryca pikseli określająca prymityw (fragment), dane gotowe do przesłania na bufor ramki Aleksander Dawid 2001-2012 rok 112

GL Shading Language (GLSL) Teksturowanie i kolorowanie fragmentów Na wejściu: fragment prymitywu Ustalona funkcjonalność Interpolowany kolor mieszany jest z wartością teksela (elementu tekstury) Efekt mgły Rasteryzacja Na wejściu: pokolorowany prymityw i położenie piksela Ustalona funkcjonalność Test przycinania Test alfa Test bufora szablonu Test bufora głębokości Na wyjściu: rysowanie w buforze ramki Aleksander Dawid 2001-2012 rok 113

GL Shading Language (GLSL) W nowoczesnych układach graficznych dano możliwość programowania funkcjonalności w dwóch poniższych etapach przetwarzania grafiki Transforamcja wierzchołków programowalna jednostka Vertex Shaders Teksturowanie i kolorowanie fragmentów programowalna jednostka Fragment Shaders (pixel shaders) Vertex Shaders Pozwala pisać własny program na transformacje wierzchołków, transformacje normalnych, transformacje współrzędnych tekstur, obliczanie świateł dla pojedynczych wierzchołków, obliczenia kolorów. W momencie użycia jednostki vertex shaders cała ustalona funkcjonalność musi być obsługiwana przez nasz program Odpowiedzialny za zapis wartości gl_position Program ma dostęp do stanu maszyny OpenGL Aleksander Dawid 2001-2012 rok 114

GL Shading Language (GLSL) Fragment Shaders Zmiana funkcjonalności w zakresie operacji Obliczenia kolorów i współrzędnych tekstur na każdy piksel Nakładanie tekstur Obliczanie mgły Obliczanie normalnych w przypadku oświetlenia na każdy piksel Fragment shaders ma dostęp do położeń poszczególnych pikseli, ale nie może ich zmieniać Na wyjściu: Nie przekazywać nic gl_fragcolor ostateczny kolor dla fragmentu gl_fragdata gdy renderowanie jest dla różnych urządzeń wyświetlających Aleksander Dawid 2001-2012 rok 115

GLSL - programowanie Inicjalizacja Każdy shader jest jak osobny program napisany w języku C i musi być skompilowany. Aplikacja w OpenGL musi mieć minimum dwa shadery (Vertex shader i Fragment Shader) Do programowania shaderów potrzebna jest obsługa OpenGL2.0 lub rozszerzenia ARB (Archtecture Review Board). Dobrym rozwiązaniem zarówno dla jednego i drugiego przypadku jest biblioteka GLEW Aleksander Dawid 2001-2012 rok 116

GLSL - programowanie Test rozszerzenia ARB Sprawdzamy czy nasza karta graficzna/system obsługują rozszerzenia GL_ARB_fragment_shader i GL_ARB_vertex_shader //Incjalizacja OpenGL (glut,wingl,glaux) glewinit(); if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader) printf("glsl OK\n"); else { printf("brak obsługi GLSL\n"); exit(1); } Aleksander Dawid 2001-2012 rok 117

GLSL - programowanie Test OpenGL2.0 Sprawdzamy czy nasza karta graficzna/system obsługują rozszerzenia GL_ARB_fragment_shader i GL_ARB_vertex_shader //Incjalizacja OpenGL (glut,wingl,glaux) glewinit(); if (glewissupported("gl_version_2_0")) printf( Gotowy na OpenGL 2.0\n"); else { printf("opengl 2.0 nie wspierane\n"); exit(1); } Aleksander Dawid 2001-2012 rok 118

GLSL - programowanie Konstrukcja programu Vertex shader glcreateshader glcreateprogram glshadersource glattacheshader glcompileshader glattacheshader FRAGMENT shader glcreateshader gllinkprogram glshadersource gluseprogram glcompileshader Aleksander Dawid 2001-2012 rok 119

GLSL - programowanie Vertex shader GLuint glcreateshader(glenum shadertype); glcreateshader glshadersource glcompileshader FRAGMENT shader glcreateshader glshadersource glcompileshader shadertype GL_VERTEX_SHADER, GL_FRAGMENT_SHADER Gluint shader; shader = glcreateshader(gl_vertex_shader); shader identyfikator shadera void glshadersource(gluint shader, int numofstrings, const char **strings, int *lenofstrings); numofstrings ilość ciągów w tablicy. strings tablica ciągów. lenofstrings tablica rozmiarów ciągów, albo NULL, oznacza ciągi zakończone znakiem zero NULL void glcompileshader(gluint shader); Aleksander Dawid 2001-2012 rok 120

GLSL - programowanie Program glcreateprogram GLuint glcreateprogram(void); Funkcja zwraca identyfikator pojemnika. Programów możemy tworzyć ile chcemy. Możemy przełączać się między tymi programami. glattacheshader void glattachshader(gluint program, GLuint shader); glattacheshader gllinkprogram void gllinkprogram(gluint program); void gluseprogram(gluint prog); prog uchwyt do programu który chcemy użyć, lub zero jako powrót do ustalonej funkcjonalności. gluseprogram Aleksander Dawid 2001-2012 rok 121

GLSL - programowanie Shader program W kodzie GLbyte vshaderstr[] = "attribute vec4 vposition; \n" "void main() \n" "{ \n" " gl_position = vposition; \n" "} \n"; W pliku zewnętrznym char *vs = NULL; vs = File2Text("test.vert"); Aleksander Dawid 2001-2012 rok 122

GLSL - programowanie char *File2Text(char *filename) { FILE *fp; char *content = NULL; int count=0; if (fn!= NULL) { fp = fopen(filename,"rt"); if (fp!= NULL) { fseek(fp, 0, SEEK_END); count = ftell(fp); rewind(fp); } } } if (count > 0) { content = (char *)malloc(sizeof(char) * (count+1)); count = fread(content,sizeof(char),count,fp); content[count] = '\0'; } fclose(fp); return content; Aleksander Dawid 2001-2012 rok 123

void UstawShadery() { char *vs,*fs; Ustawienie shadera- przykład v = glcreateshader(gl_vertex_shader); f = glcreateshader(gl_fragment_shader); vs = File2Text("toon.vert"); //vertex shader fs = File2Text("toon.frag"); //fragment shader const char * vv = vs; const char * ff = fs; glshadersource(v, 1, &vv,null); glshadersource(f, 1, &ff,null); free(vs);free(fs); glcompileshader(v); glcompileshader(f); p = glcreateprogram(); glattachshader(p,v); glattachshader(p,f); } gllinkprogram(p); gluseprogram(p); Aleksander Dawid 2001-2012 rok 124

Sprawdzanie poprawności kodu Dla shaderów nie ma możliwości sprawdzenia poprawności kodu. Narzędzia dostępne w OpenGL 2.0 void glgetshaderiv(gluint object, GLenum type, int *param); object uchwyt do shadera lub programu type GL_COMPILE_STATUS. param zwracana wartość, GL_TRUE kompilacja prawidłowa, GL_FALSE błędy przy kompilacji. void glgetprogramiv(gluint object, GLenum type, int *param); object uchwyt do shadera lub programu type GL_LINK_STATUS. param zwracana wartość, GL_TRUE kompilacja prawidłowa, GL_FALSE błędy przy kompilacji. Aleksander Dawid 2001-2012 rok 125

Poprawności kodu InfoLog W przypadku błędów podczas przetwarzania programu przez kartę graficzną, sterownik generuje dziennik (InfoLog). Format tego dziennika zależny jest od sterownika urządzenia. void glgetshaderinfolog(gluint object, int maxlen, int *len, char *log); void glgetprograminfolog(gluint object, int maxlen, int *len, char *log); object uchwyt do shadera lub programu maxlen maksymalna liczba znaków do pobrania z pliku InfoLog. len zwraca aktualny rozmiar pliku InfoLog. log Nazwa pliku InfoLog. Pobranie rozmiaru pliku InfoLog void glgetshaderiv(gluint object, GLenum type, int *param); void glgetprogramiv(gluint object, GLenum type, int *param); object uchwyt do shadera lub programu type GL_INFO_LOG_LENGTH. param rozmiar pliku InfoLog. Aleksander Dawid 2001-2012 rok 126

Odczyt InfoLog przykład void printshaderinfolog(gluint obj) { int infologlength = 0; int charswritten = 0; char *infolog; //glgetprogramiv(obj, GL_INFO_LOG_LENGTH,&infologLength); glgetshaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength); } if (infologlength > 0) { infolog = (char *)malloc(infologlength); glgetshaderinfolog(obj, infologlength, &charswritten, infolog); printf("%s\n",infolog); free(infolog); } Aleksander Dawid 2001-2012 rok 127

Kasowanie shaderów Przed skasowaniem shadery muszą być odłączone od programu void gldetachshader(gluint program, GLuint shader); program identyfikator programu. shader identyfikator shadera do odłączenia. Kasowanie void gldeleteshader(gluint id); void gldeleteprogram(gluint id); id identyfikator programu lub shadera, który ma zostać skasowany. Aleksander Dawid 2001-2012 rok 128

Komunikacja OpenGL Shader Wynik działania programu shadera przekazywany jest tylko w postaci graficznej do bufora koloru lub głębokości, więc komunikacja jest tylko jednokierunkowa. GLSL pozwala na definiowanie zmiennych do komunikacji z shaderami GLSL obsługuje dwa modyfikatory zmiennych Attribute Uniform Zmienne używające tych modyfikatorów są tylko do odczytu przez shader. Inną metodą przesyłania danych do shaderów są tekstury, które mogą reprezentować tablicę liczb. Aleksander Dawid 2001-2012 rok 129

UNIFORM Zmienne Wartości mogą być zmieniane tylko przez prymitywy. Aby ustawić zmienną UNIFORM trzeba najpierw pobrać jej adres z programu shadera w postaci nazwy. Program shadera musi być zlinkowany i użyty. GLint glgetuniformlocation(gluint program, const char *name); program identyfikator programu. name nazwa zmiennej. Zwracana wartość z tej funkcji to identyfikator położenia, na podstawie którego możemy przypisać wartość do zmiennej. void gluniform1f(glint location, GLfloat v0); void gluniform2f(glint location, GLfloat v0, GLfloat v1); void gluniform3f(glint location, GLfloat v0, GLfloat v1, GLfloat v2); void gluniform4f(glint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); GLint gluniform{1,2,3,4}fv(glint location, GLsizei count, GLfloat *v); Aleksander Dawid 2001-2012 rok 130

Zmienne GLint gluniformmatrix{2,3,4}fv(glint location, GLsizei count, GLboolean transpose, GLfloat *v); location położenie zmiennej. count liczba macierzy. transpose macierz transponowana Anm=Bmn v tablica liczb zmiennoprzecinkowych. Ustawione wartości istnieją tak długo w pamięci dopóki program nie zostanie ponownie zlinkowany. PRZYKŁAD Aleksander Dawid 2001-2012 rok 131

ATTRIBUTE Zmienne Wartości mogą być ustawiane na wierzchołek pomiędzy glbegin glend. Aby ustawić zmienną ATTRIBUTE trzeba najpierw pobrać jej adres z programu shadera w postaci nazwy. Program shadera musi być zlinkowany i użyty. GLint glgetattriblocation(gluint program,char *name); program identyfikator programu. name nazwa zmiennej. Zwracana wartość z tej funkcji to identyfikator położenia, na podstawie którego możemy przypisać wartość do zmiennej. void glvertexattrib1f(glint location, GLfloat v0); void glvertexattrib2f(glint location, GLfloat v0, GLfloat v1); void glvertexattrib3f(glint location, GLfloat v0, GLfloat v1,glfloat v2); void glvertexattrib4f(glint location, GLfloat v0, GLfloat v1,,glfloat v2, GLfloat v3); GLint glvertexattrib{1,2,3,4}fv(glint location, GLfloat *v); Aleksander Dawid 2001-2012 rok 132

ATTRIBUTE przykład Zmienne glbegin(gl_triangle_strip); glvertexattrib1f(loc,5.0); glvertex2f(-1,1); glvertexattrib1f(loc,2.0); glvertex2f(1,1); glvertexattrib1f(loc,-2.0); glvertex2f(-1,-1); Zwracana wartość glvertexattrib1f(loc,-2.0); z tej funkcji to identyfikator położenia, na podstawie którego możemy przypisać glvertex2f(1,-1); wartość do zmiennej. glend(); Aleksander Dawid 2001-2012 rok 133

Typy zmiennych shader program Typy proste int bool float Typy wektorowe vec{2,3,4} (float) bvec{2,3,4} (bool) ivec{2,3,4} (int) Typy macierzowe mat2 macierz 2x2 mat3 - macierz 3x3 mat4 - macierz 4x4 Aleksander Dawid 2001-2012 rok 134

Typy zmiennych shader program Typy teksturowe, dotyczą tekseli sampler1d dla tekstur 1D sampler2d dla tekstur 2D sampler3d dla tekstur 3D Tablice tych zmiennych deklarujemy tak samo jak w języku C vect3 A[10]; mat4 Tab[2]; Struktury struct spotlight { vec3 kierunek; vec3 kolor; }; spotlight A; A.kierunek=vec3(1.0,1.0,1.0); Aleksander Dawid 2001-2012 rok 135

Instrukcje sterujące IF-ELSE if (bool warunek)... else... FOR for (inicjalizacja; warunek; zmiana wartości)... WHILE while (warunek)... DO-WHILE do... while (warunek) Aleksander Dawid 2001-2012 rok 136

Funkcje Funkcje deklaruje się podobnie jak w języku C void main() vec4 ChangeColor(in float intensity){ vec4 color; color = vec4(intensity, intensity, intensity,1.0); return(color); } Modyfikatory: in,out,inout Domyślny in Aleksander Dawid 2001-2012 rok 137

Zmienna varying Zmienna przenoszona pomiędzy programem Vertex Shader a Fragment Shader varying float intensity; Aleksander Dawid 2001-2012 rok 138

Przykład Vertex Shader void main(){ gl_position = gl_modelviewprojectionmatrix * gl_vertex; } Fragment Shader void main(){ gl_fragcolor = gl_color; } Aleksander Dawid 2001-2012 rok 139

Przykład Windows API GLSL Omówienie interfejsu OpenGL dla Windows Aleksander Dawid 2001-2016 rok 140

Powiązanie technologii GLSL z WinApi Czynności wstępne case WM_CREATE: /* Tworzenie kontekstu renderowania OpenGL */ ghdc = GetDC(hWnd); setuppixelformat(ghdc); ghrc = wglcreatecontext(ghdc); wglmakecurrent(ghdc, ghrc); GetClientRect(hWnd, &rect); initializegl(rect.right, rect.bottom); SetTimer(hWnd, 101, 5, NULL); break; Aleksander Dawid 2001-2012 rok 141

Powiązanie technologii GLSL z WinApi Pobranie kontekstu urządzenia wyświetlającego ghdc = GetDC(hWnd); Ustalenie formatu Pikseli setuppixelformat(ghdc); Utworzenie kontekstu OpenGL ghrc = wglcreatecontext(ghdc); Ustawienie kontekstu OpenGL jako bierzącego wglmakecurrent(ghdc, ghrc); Aleksander Dawid 2001-2012 rok 142

Powiązanie technologii GLSL z WinApi Pobranie rozmiaru okna roboczego GetClientRect(hWnd, &rect); Inicjalizacja parametrów OpenGL i GLSL initializegl(rect.right, rect.bottom); Ustawienie timera jako dodatkowego wątku kontrolującego animację SetTimer(hWnd, 101, 5, NULL); Aleksander Dawid 2001-2012 rok 143

Inicjalizacja grafiki OpenGL GLvoid initializegl(glsizei width, GLsizei height) { glclearcolor( 0.0f, 0.0f, 0.0f, 0.0f); glcleardepth( 1.0 ); glshademodel(gl_smooth); glenable(gl_depth_test); InitGLSL(); InitShaders(); } GLSL InitGLSL(); InitShaders(); Aleksander Dawid 2001-2012 rok 144

Inicjalizacja biblioteki Shaderów Do inicjalizacji shaderów służy biblioteka GLEW: The OpenGL Extension Wrangler Library #include <GL/glew.h> W celu wykorzystania tej biblioteki w systemie Windows trzeba wykonać kompilację jej kodu źródłowego glew32d.dll biblioteka dynamiczna glew32d.lib biblioteka statyczna Biblioteka wykorzystuje zarówno kartę graficzną jak i emuluje bibliotekę shaderów w przypadku ich braku. Aleksander Dawid 2001-2012 rok 145

Inicjalizacja biblioteki Shaderów Instrukcja glewinit(); inicjalizuje bibliotekę GLEW GLvoid InitGLSL(){ glewinit(); if (GLEW_VERSION_2_0){ MessageBox(ghWnd, "INFO: OpenGL 2.0 wspierany", Informacja",MB_OK); }else{ MessageBox(ghWnd, "INFO: OpenGL 2.0 nie wspierany", " Informacja",MB_OK); } } glewinit(); musi być wywołane po inicjalizacji biblioteki OpenGL Jeżeli zmienna boolowska GLEW_VERSION_2_0=prawda to możemy skorzystać z funkcjonalności jaką oferuje standard OpenGL2.0 Aleksander Dawid 2001-2012 rok 146

GLvoid InitShaders(){ char shaderfn[]="wave.vert"; char fragmentfn[]="wave.frag"; char Info[64]; Program Shaderów char *vssource = textfileread(shaderfn); if(vssource==null){ sprintf(info,"plik: %s nie znaleziony",shaderfn); MessageBox(ghWnd, Info, "Informacja",MB_OK); exit(0); } char *fssource = textfileread(fragmentfn); if(fssource==null){ sprintf(info,"plik: %s nie znaleziony",fragmentfn); MessageBox(ghWnd, Info, "Informacja",MB_OK); exit(0); } Aleksander Dawid 2001-2012 rok 147

Program Shaderów const char * vv = vssource; const char * ff = fssource; vs = glcreateshader(gl_vertex_shader); fs = glcreateshader(gl_fragment_shader); glshadersource(vs, 1, &vv, NULL); glshadersource(fs, 1, &ff, NULL); free(vssource); free(fssource); glcompileshader(vs); glcompileshader(fs); printlog(vs); printlog(fs); Aleksander Dawid 2001-2012 rok 148

Program Shaderów sp = glcreateprogram(); glattachshader(sp, vs); glattachshader(sp, fs); gllinkprogram(sp); printlog(sp); gluseprogram(sp); } Aleksander Dawid 2001-2012 rok 149

Falująca powierzchnia Efekt falującej powierzchni jest często stosowany w grafice komputerowej; woda, flaga, trawa itd. Do czasu zanim zostały wprowadzone shadery wykonywany był przez procesor główny komputera. Dla wielkie ilości wierzchołków był praktycznie niemożliwy do wykonania w grach komputerowych. Aleksander Dawid 2001-2012 rok 150

Falująca powierzchnia Algorytm Start Inicjalizacja OpenGL Wierzchołki Vertex Shader Pixel Shader i<n i=i+1 Aleksander Dawid 2001-2012 rok 151

Vertex shader Fala uniform float wavetime; uniform float wavewidth; uniform float waveheight; void main(void) { vec4 gv = vec4(gl_vertex); gv.z = sin(wavewidth * gv.x + wavetime) * cos(wavewidth * gv.y + wavetime) * waveheight; } gl_position = gl_modelviewprojectionmatrix * gv; Aleksander Dawid 2001-2012 rok 152

Vertex shader Fala uniform float wavetime; uniform float wavewidth; uniform float waveheight; Zmienne uniform to zmienne dostępne dla naszego programu. Przy ich pomocy możemy w czasie rzeczywistym modyfikować zachowanie fali. Aby zmodyfikować te zmienne musi nasz program shadera być już uruchomiony. GLvoid InitWave(){ wavetimeloc = glgetuniformlocation(sp, "wavetime"); wavewidthloc = glgetuniformlocation(sp, "wavewidth"); waveheightloc = glgetuniformlocation(sp, "waveheight"); printlog(sp); } Aleksander Dawid 2001-2012 rok 153

Vertex shader Fala GLvoid initializegl(glsizei width, GLsizei height) {... InitShaders(); InitWave(); } Adresy w pamięci karty graficznej GLint wavetimeloc; GLint wavewidthloc; GLint waveheightloc; Inicjalizacja zmiennych w CPU GLfloat wavetime = 0.0; Glfloat wavewidth = 0.2; Glfloat waveheight = 5.0; Glfloat wavefreq = 0.1; Aleksander Dawid 2001-2012 rok 154

Vertex shader Fala gl_vertex - wierzchołki, które będą poddane obróbce przez nasz program Równanie fali płaskiej. z f ( x, y) Asin( Wx t)cos( Wy t) Modyfikacji podlega tylko składowa z gv.z = sin(wavewidth * gv.x + wavetime) * cos(wavewidth * gv.y + wavetime) * waveheight; Zmodyfikowane pozycje wierzchołków gl_position = gl_modelviewprojectionmatrix * gv; Aleksander Dawid 2001-2012 rok 155

Fragment shader Fala gl_fragcolor - Ostateczny kolor fragmentów void main() { gl_fragcolor[0] = gl_fragcoord[0] / 400.0; gl_fragcolor[1] = gl_fragcoord[1] / 400.0; gl_fragcolor[2] = 1.0; } gl_fragcoord - Współrzędne fragmentów Aleksander Dawid 2001-2012 rok 156

Płaszczyzna wielokatów Fala GLvoid PlainSurface() { int i,j; glbegin(gl_quads); for (i = -50; i < 50; i++) for (j = -50; j < 50; j++) { glvertex2f(i, j); glvertex2f(i + 1, j); glvertex2f(i + 1, j + 1); glvertex2f(i, j + 1); } glend(); } Aleksander Dawid 2001-2012 rok 157

Pętla animacji Fala GLvoid drawscene(glvoid) { glclearcolor( 0.0f, 0.0f, 0.4f, 0.0f); glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); gluniform1f(wavetimeloc, wavetime); gluniform1f(wavewidthloc, wavewidth); gluniform1f(waveheightloc, waveheight); } PlainSurface(); wavetime += wavefreq; SWAPBUFFERS; Animacja wykonywana jest w osobnym wątku ustawionym przez timer wavewidth, waveheight - Można modyfikować w głównym wątku Aleksander Dawid 2001-2012 rok 158

Cieniowanie Phonga Stosowane bardzo często w grafice wektorowej w celu reprezentacji rozbłysków Vertex Shader varying vec3 N; varying vec3 v; void main(void) { v = vec3(gl_modelviewmatrix * gl_vertex); N = normalize(gl_normalmatrix * gl_normal); gl_position = gl_modelviewprojectionmatrix * gl_vertex; } Aleksander Dawid 2001-2012 rok 159

Fragment Shader varying vec3 N; varying vec3 v; Cieniowanie Phonga void main (void) { vec3 L = normalize(gl_lightsource[0].position.xyz - v); vec3 E = normalize(-v); vec3 R = normalize(-reflect(l,n)); L wektor światła E odwrotny wektor modelu R wektor odbicia Aleksander Dawid 2001-2012 rok 160

Fragment Shader Cieniowanie Phonga //Kolor otoczenia (Ambient): vec4 Iamb = gl_frontlightproduct[0].ambient; //Kolor rozpraszania (Diffuse): vec4 Idiff = gl_frontlightproduct[0].diffuse * max(dot(n,l), 0.0); Idiff = clamp(idiff, 0.0, 1.0); // Kolor rozbłysków (Specular): vec4 Ispec = gl_frontlightproduct[0].specular *pow(max(dot(r,e),0.0),0.3*gl_frontmaterial.shininess); Ispec = clamp(ispec, 0.0, 1.0); // Całkowity Kolor: gl_fragcolor = gl_frontlightmodelproduct.scenecolor + Iamb + Idiff + Ispec; } Aleksander Dawid 2001-2012 rok 161

Cieniowanie Phonga Przekazywanie zmiennych Zmienne typu varying mogą być przekazywane między vertex shader a fragment shader Cały algorytm bazuje na wektorach normalnych, które liczone są w jednostce vertex shader. Aleksander Dawid 2001-2012 rok 162

Cieniowanie Phonga Porównanie standardowego cieniowania wielokątów z cieniowaniem Phonga przy użyciu shaderów. Aleksander Dawid 2001-2012 rok 163

WebGL Standard OpenGL ES Aleksander Dawid 2001-2016 rok 164

WebGL Standard stworzony do obróbki grafiki 3D w przeglądarce internetowej. WebGL bazuje na bibliotekach OpenGL for Embeded Systems. Grafika tworzona jest w całości przez kartę graficzną, która obsługuje minimalnie OpenGL 2.0 lub OpenGL ES 2.0. Główni dostawcy przeglądarek Apple (Safari), Google (Chrome), Mozilla (Firefox), i Opera (Opera) są członkami WebGL Working Group. Aleksander Dawid 2001-2016 rok 165

WebGL WebGL korzysta z osadzenia w znaczniku canvas z HTML5. Programowanie API WebGL odbywa się przy pomocy języka JavaScript. WebGL jest w 100% kompatybilny z OpenGL ES. Do transformacji wierzchołków i renderowania fragmentów wykorzystuje programy shaderów. WebGL nie wymaga instalowania dodatkowych bibliotek. Aleksander Dawid 2001-2016 rok 166

WebGL Inicjalizacja okna WebGL Kod HTML5 <HTML> <HEAD> <SCRIPT type="text/javascript"> // Kod JavaScript </SCRIPT> </HEAD> <BODY onload="startgl()" bgcolor="white"> <canvas id="glid" width="640" height="480"> Brak wsparcia dla technologii HTML5 </canvas> </BODY> </HTML> Aleksander Dawid 2001-2016 rok 167

Inicjalizacja okna WebGL Kod JavaScript WebGL var gl; function startgl(){ var canvas=document.getelementbyid("glid"); gl = null; try{gl=canvas.getcontext("experimental-webgl");} catch(e){} } if(!gl){ alert("brak wsparcia sprzętowego dla OpenGL (WebGL)"); return; }else{ gl.clearcolor(0.2,0.2,0.6,1.0); gl.clear(gl.color_buffer_bit gl.depth_buffer_bit); } Aleksander Dawid 2001-2016 rok 168

Rysowanie WebGL W celu wyświetlenia wierzchołka w oknie WebGL potrzeba wykonać następujące czynności. 1. Utworzyć Vertex Shader 2. Utworzyć FragmentShader 3. Skompilować i zlinkować program shaderów 4. Wpisać wierzchołki do tablicy 5. Uruchomić program shaderów 6. Pobrać atrybut położenia z vertex shadera 7. Przekazać położenia z tablicy do vertex shadera 8. Wydać komendą wyświetlania tablicy Dla wielu różnych obiektów czynności te trzeba powtórzyć. Aleksander Dawid 2001-2016 rok 169

Deklaracja tablicy wierzchołków A. Przypisanie w trakcie deklaracji tablicy Punkty3D = [ 0.0, 0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, 0.0]; B. Wypełnianie tablicy algorytmicznie WebGL Punkty3D = []; skok=0.5; iter=-0.5; for(i=0;i<9;i++){ if(i%3==0){ Punkty3D.push(iter); iter=iter+skok; }else{ Punkty3D.push(0.0); } } Aleksander Dawid 2001-2016 rok 170

Deklaracja Vertex Shadera WebGL A. Wewnątrz ciągu znaków var VShader="attribute vec4 pozycja; "+ " void main() " + "{" + "gl_position = pozycja;"+ "gl_pointsize = 30.0;"+ "}"; B. Wewnątrz dodatkowego znacznika <SCRIPT> <script id="vertex-shader" type="x-shader/x-vertex"> attribute vec4 pozycja; void main() { gl_position = pozycja; gl_pointsize = 30.0; } </script> Aleksander Dawid 2001-2016 rok 171

Przekazywanie wierzchołków A. Przez zmienne attribute Zmienna gl_position przekazuje wierzchołki do dalszego renderowania. attribute vec4 pozycja; void main() { gl_position = pozycja; gl_pointsize = 30.0; } WebGL var coor = gl.getattriblocation(shaderprogram, "pozycja"); gl.vertexattrib4f(coor, g_points[0], g_points[1], g_points[2], 1.0); gl.drawarrays(gl.points, 0, 1); //Przekazanie 1 wierzchołka Wada: transfer z CPU do GPU każdego wierzchołka. Aleksander Dawid 2001-2016 rok 172

Przekazywanie wierzchołków B. Przez bufor GPU WebGL Punkty3D = [ 0.0, 0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, 0.0]; var vertex_buffer = gl.createbuffer(); gl.bindbuffer(gl.array_buffer, vertex_buffer); gl.bufferdata(gl.array_buffer, new Float32Array(Punkty3D), gl.static_draw); // kopiowanie danych wierzchołków //Połaczenie bufora z Vertex Shaderem var coord = gl.getattriblocation(shaderprogram, "pozycja"); gl.vertexattribpointer(coord, 3, gl.float, false, 0, 0); gl.enablevertexattribarray(coord); //Przekazanie 3 wierzchołków z bufora GPU gl.drawarrays(gl.points, 0, Punkty3D.length/3); Aleksander Dawid 2001-2016 rok 173

Fragment Shader WebGL <script id="fragment-shader" type="x-shader/x-fragment"> precision mediump float; uniform vec4 kolor; void main() { gl_fragcolor = kolor; } </script> highp, mediump, lowp precyzja obliczeń Do fragment shadera parametry można przesyłać tylko w zmiennych uniform. Aleksander Dawid 2001-2016 rok 174

Fragment Shader Zmiana koloru przez zmienną var nk = gl.getuniformlocation(shaderprogram, "kolor"); gl.uniform4f( nk, 1.0, 0.0, 0.0, 1.0 ); gl.drawarrays(gl.points, 0, 1); gl.uniform4f( nk, 0.0, 1.0, 0.0, 1.0 ); gl.drawarrays(gl.points, 1, 1); gl.uniform4f( nk, 0.0, 0.0, 1.0, 1.0 ); gl.drawarrays(gl.points, 2, 1); WebGL gl.drawarrays(gl.points, start, length); start offset w buforze GPU lenght rozmiar liczony w rozmiarze wektor 3-elementowego. Aleksander Dawid 2001-2016 rok 175

Fragment Shader WebGL Zmiana koloru ze względu na dane w Vertex Shader attribute vec4 pozycja; varying vec4 N; //zmienna dostępna we Fragment Shader void main() { N = pozycja; gl_position = pozycja; gl_pointsize = 30.0; } Przekazujemy w zmiennej N pozycje każdego z wierzchołków Aleksander Dawid 2001-2016 rok 176

Fragment Shader Zmiana koloru ze względu na dane w Vertex Shader precision mediump float; varying vec4 N; WebGL void main() { vec4 kolor; if(n.x<0.0) kolor=vec4(1.0,0.0,0.0,1.0); if(n.x==0.0) kolor=vec4(0.0,1.0,0.0,1.0); if(n.x>0.0) kolor=vec4(0.0,0.0,1.0,1.0); } gl_fragcolor = kolor; gl.drawarrays(gl.points, 0, Punkt3D.length/3); Aleksander Dawid 2001-2016 rok 177

Kompilacja Shaderów WebGL var vertelem = document.getelementbyid(vertexshaderid); //Pobranie lokalizacji znacznika <SCRIPT id=vertexshaderid> vertshdr = gl.createshader(gl.vertex_shader); gl.shadersource(vertshdr, vertelem.text); // vertelem.text tekst wewnątrz znacznika gl.compileshader(vertshdr); if (!gl.getshaderparameter(vertshdr, gl.compile_status)) { var msg = "Vertex shader nie można skompilowć:" + "<pre>" + gl.getshaderinfolog(vertshdr) + "</pre>"; alert(msg); console.log(msg); return -1; } Aleksander Dawid 2001-2016 rok 178

Kompilacja Shaderów WebGL if(n.x<0) kolor=vec4(1.0,0.0,0.0,1.0); Aleksander Dawid 2001-2016 rok 179

Kompilacja Shaderów WebGL fragshdr = gl.createshader(gl.fragment_shader); gl.shadersource(fragshdr, fragelem.text); gl.compileshader(fragshdr); var program = gl.createprogram(); gl.attachshader(program, vertshdr); gl.attachshader(program, fragshdr); gl.linkprogram(program); if (!gl.getprogramparameter(program, gl.link_status)) { var msg = "Shader program nie można zlinkować:" + "<pre>" + gl.getprograminfolog(program) + "</pre>"; alert(msg); console.log(msg); return -1; } Aleksander Dawid 2001-2016 rok 180

Użycie Shaderów WebGL var vertex_buffer = gl.createbuffer(); gl.bindbuffer(gl.array_buffer, vertex_buffer); gl.bufferdata(gl.array_buffer, new Float32Array(g_points), gl.static_draw); var shaderprogram = initshaders( gl, "vertex-shader", "fragment-shader" ); //Program shaderów musi być uruchomiony gl.useprogram(shaderprogram); var coord = gl.getattriblocation(shaderprogram, "pozycja"); gl.vertexattribpointer(coord, 3, gl.float, false, 0, 0); gl.enablevertexattribarray(coord); gl.clearcolor(0.6,0.6,1.0,1.0); //Ustawienie koloru tła gl.clear(gl.color_buffer_bit gl.depth_buffer_bit); gl.drawarrays(gl.points, 0, g_points.length/3); Aleksander Dawid 2001-2016 rok 181

Rysowanie trójkątów Położenia wierzchołków g_points = [ 0.0, 0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, 0.0]; Kolory wierzchołków color_points = [ 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0,]; Vertex shader attribute vec4 pozycja; attribute vec4 pozycjacolor; varying vec4 N; WebGL Wypełnianie gradientowe void main() { gl_position = pozycja; N = pozycjacolor; } Aleksander Dawid 2001-2016 rok 182

Rysowanie trójkątów Fragment shader precision mediump float; varying mediump vec4 N; void main() { gl_fragcolor = N; } WebGL Wypełnianie gradientowe Inicjalizacja buforów var vertex_buffer = gl.createbuffer(); gl.bindbuffer(gl.array_buffer, vertex_buffer); gl.bufferdata(gl.array_buffer, new Float32Array(g_points), gl.static_draw); var VerticesColorBuffer = gl.createbuffer(); gl.bindbuffer(gl.array_buffer, VerticesColorBuffer); gl.bufferdata(gl.array_buffer, new Float32Array(color_points), gl.static_draw); Aleksander Dawid 2001-2016 rok 183

Rysowanie trójkątów WebGL Przed samym wyświetleniem gl.bindbuffer(gl.array_buffer, vertex_buffer); gl.vertexattribpointer(coord, 3, gl.float, false, 0, 0); gl.bindbuffer(gl.array_buffer, VerticesColorBuffer); gl.vertexattribpointer(coordcolor, 4, gl.float, false, 0, 0); gl.drawarrays(gl.triangles, 0, 3); Aleksander Dawid 2001-2016 rok 184

Oświetlenie WebGL Wektory normalne normal_points = [ 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0]; Aleksander Dawid 2001-2016 rok 185

Oświetlenie Vertex Shader attribute vec3 pozycja; attribute vec3 pozycjanorm; varying vec3 N; varying vec3 Pos; WebGL void main() { gl_position = vec4(pozycja,1.0); N = pozycjanorm; //Przekazanie normalnych do Fragment shadera Pos = pozycja; //Przekazanie położenia do Fragment shadera } Aleksander Dawid 2001-2016 rok 186

Oświetlenie Fragment Shader precision mediump float; varying vec3 N; varying vec3 Pos; WebGL void main() { vec4 Ambient = vec4(0.6,0.0,0.0,1.0); // Ambient Color vec4 Diffuse = vec4(1.0,1.0,0.0,1.0); // Diffuse Color vec3 Light_pos = vec3(0.0,-0.2,0.3); // Wektor Promienia od źródła światła do wierzchołka vec3 Ray = normalize(light_pos - Pos); // Iloczyn skalarny wektora Normalnego i wektora promienia float DiffAmp = max(dot(n,ray), 0.0); vec4 DiffV = Diffuse*DiffAmp; DiffV = clamp(diffv, 0.0, 1.0); // Normalizacja do [0.0,1.0] vec4 Suma = Ambient + DiffV; gl_fragcolor = Suma; } Aleksander Dawid 2001-2016 rok 187

Teksturowanie attribute vec3 pozycja; attribute vec2 atexturecoord; varying mediump vec2 vtexturecoord; void main() { gl_position = vec4(pozycja,1.0); vtexturecoord = atexturecoord; } WebGL W procesie nakładania tekstur na trójkąty bardzo ważne są współrzędne tekstury. Przesyłana one są z Vertex Shadera do Fragment Shadera Vertex Shader Fragment Shader varying mediump vec2 vtexturecoord; uniform sampler2d usampler; } void main() { gl_fragcolor = texture2d(usampler, vtexturecoord); Aleksander Dawid 2001-2016 rok 188

Teksturowanie WebGL Ustalenie współrzędnych tekstury dla kwadratu=2 trójkąty Wierzchołki var si=0.5; wall_points = [ -si, -si, 0.0, si, -si, 0.0, -si, si, 0.0, -si, si, 0.0, si, -si, 0.0, si, si, 0.0 ]; 0.0, 1.0 Współrzędne tekstury wall_texcoor = [ 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 ]; 1.0, 1.0 0.0, 0.0 1.0, 0.0 Aleksander Dawid 2001-2016 rok 189

Teksturowanie WebGL Ładowanie Obrazka InitTextures=function() { walltexture = gl.createtexture(); wallimage = new Image(); wallimage.src = "jatex.jpg"; } Sprawdzenie czy rozmiary obrazka są potęgą liczby 2 function ispowerof2(value) { return (value & (value - 1)) == 0; }; Aleksander Dawid 2001-2016 rok 190

Teksturowanie WebGL Parametry tekstury TextureParams=function(texture,image) { gl.bindtexture(gl.texture_2d, texture); gl.teximage2d(gl.texture_2d, 0, gl.rgba, gl.rgba, gl.unsigned_byte, image); if (ispowerof2(image.width) && ispowerof2(image.height)) { gl.texparameteri(gl.texture_2d, gl.texture_mag_filter, gl.linear); gl.texparameteri(gl.texture_2d, gl.texture_min_filter, gl.linear_mipmap_linear); gl.generatemipmap(gl.texture_2d); } else { gl.texparameteri(gl.texture_2d, gl.texture_wrap_s, gl.clamp_to_edge); gl.texparameteri(gl.texture_2d, gl.texture_wrap_t, gl.clamp_to_edge); gl.texparameteri(gl.texture_2d, gl.texture_min_filter, gl.linear); } } Aleksander Dawid 2001-2016 rok 191

Teksturowanie WebGL Problemy przy teksturowaniu WebGL Asynchroniczne wczytywanie plików graficznych. Problem dotyczy JavaScript i polega na wcześniejszym wywołaniu instrukcji renderujących teksturę niż wczytanie samego pliku który ma być teksturą. Zabezpieczenia przeglądarek internetowych. Pliki zewnętrzne (obrazy tekstur) nie mogą być pobierane podczas uruchamiania strony internetowej (plik HTML) z lokalnego folderu. Obraz taki można tylko pobrać z serwera WWW (HTTP). Aleksander Dawid 2001-2016 rok 192

Teksturowanie WebGL Renderowanie tekstury na trójkątach. wallimage.onload = function() { gl.clearcolor(0.9,0.9,1.0,1.0); //Ustawienie koloru tła gl.clear(gl.color_buffer_bit gl.depth_buffer_bit); gl.bindbuffer(gl.array_buffer, vertex_buffer); gl.vertexattribpointer(coord, 3, gl.float, false, 0, 0); gl.bindbuffer(gl.array_buffer, texcoor_buffer); gl.vertexattribpointer(texturecoordattribute, 2, gl.float, false, 0, 0); var textureunit = 1; TextureParams(wallTexture,wallImage); } gl.activetexture(gl.texture0+textureunit); gl.bindtexture(gl.texture_2d, walltexture); gl.uniform1i(samp, textureunit); gl.drawarrays(gl.triangles, 0, 6); Aleksander Dawid 2001-2016 rok 193

Teksturowanie WebGL Ustalenie współrzędnych tekstury dla kwadratu=2 trójkąty 0.0, 1.0 1.0, 1.0 0.0, 0.0 1.0, 0.0 0.0, 1.0 1.0, 1.0 0.0, 0.0 1.0, 0.0 Aleksander Dawid 2001-2016 rok 194

Rzutowanie perspektywiczne WebGL Aleksander Dawid 2001-2016 rok 195

WebGL Aleksander Dawid 2001-2016 rok 196 Rzutowanie perspektywiczne Macierz perspektywy P v v far near far near far near far near ar P * 0 * 2* 0 0 1 0 0 0 0 2 tan 0 0 0 0 / 2 tan

WebGL Aleksander Dawid 2001-2016 rok 197 Rzutowanie perspektywiczne Macierz Widoku M MW P v v MW * * 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 Macierz Translacji x x z y x z y x T x T z y x x T T T z y x z y x T T T MT 1* *0 *0 *1 1 0 1 0 0 0 0 1 0 0 0 0 1,1,,,1,, 1 0 1 0 0 0 0 1 0 0 0 0 1 Macierz Skalowania 1 0 0 0 0 0 0 0 0 0 0 0 0 z y x S S S MS

WebGL Aleksander Dawid 2001-2016 rok 198 Rzutowanie perspektywiczne Macierze Obrotu wokół osi x 1 0 0 0 0 ) cos( ) sin( 0 0 ) sin( ) cos( 0 0 0 0 1 O x Macierze Obrotu wokół osi y 1 0 0 0 0 ) cos( 0 ) sin( 0 0 1 0 0 ) sin( 0 ) cos( O y Macierze Obrotu wokół osi z 1 0 0 0 0 1 0 0 0 0 ) cos( ) sin( 0 0 ) sin( ) cos( O z

Rzutowanie perspektywiczne WebGL Macierz perspektywy (JavaScript) makeperspective=function(fieldofviewinradians, aspect, near, far) { var f = Math.tan(Math.PI * 0.5-0.5 * fieldofviewinradians); var rangeinv = 1.0 / (near - far); return [ f / aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, (near + far) * rangeinv, -1, 0, 0, near * far * rangeinv * 2, 0 ]; }; Aleksander Dawid 2001-2016 rok 199

Rzutowanie perspektywiczne WebGL makeident=function() { return [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ]; }; perspectivematrix = makeperspective(45.0*math.pi/180.0, 400.0/400.0, 0.1, 100.0); MMatrix = makeident(); Przekazanie macierzy perspektywy i modelu do Vertex Shadera var PM = gl.getuniformlocation(shaderprogram, "ProjMatrix"); gl.uniformmatrix4fv(pm, false, new Float32Array(perspectiveMatrix)); var MM = gl.getuniformlocation(shaderprogram, "ModelMatrix"); gl.uniformmatrix4fv(mm, false, new Float32Array(MMatrix)); Aleksander Dawid 2001-2016 rok 200

Rzutowanie perspektywiczne WebGL Perspektywa (C, Vertex Shader) attribute vec3 pozycja; attribute vec3 pozycjanorm; uniform mat4 ProjMatrix; uniform mat4 ModelMatrix; varying vec3 N; varying vec3 Pos; void main() { gl_position = ProjMatrix*ModelMatrix*vec4(pozycja,1.0); N = pozycjanorm; Pos = pozycja; } Aleksander Dawid 2001-2016 rok 201

Translacje WebGL Wektor przesunięcia trans = [1.0, -1.0, -4.0]; Przekazanie do Vertex Shadera var trans = gl.getattriblocation(shaderprogram, "TransW"); gl.vertexattrib4f(trans, trans[0], trans[1], trans[2], 1.0); Translacja Vertex Shadera void main() { mat4 TrMat = mat4( vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(transw.x, TransW.y, TransW.z, 1.0) ); mat4 ModMat = ModelMatrix*TrMat; gl_position = ProjMatrix*ModMat*vec4(pozycja,1.0); } Aleksander Dawid 2001-2016 rok 202

Translacje WebGL Przykład. Przesuwanie trójkąta w kierunku Z Aleksander Dawid 2001-2016 rok 203

Animacja WebGL Animacja wywoływana jest z poziomu JavaScript window.requestanimationframe(render); Metoda z klasy Window wywołuje funkcję Render render=function() { gl.clear(gl.color_buffer_bit); if(xcor>0.8) step=-step; if(xcor<-0.8) step=-step; Xcor+=step; } gl.uniform1f( Xpos, Xcor ); gl.uniform1f( Scale, 8.0 ); gl.drawarrays(gl.triangle_fan, 0, vertices.length/3); window.requestanimationframe(render); Aleksander Dawid 2001-2016 rok 204

Najważniejsze funkcje języka Shaderów Konwersja radianów do stopni float radians(float degrees) vec2 radians(vec2 degrees) vec3 radians(vec3 degrees) vec4 radians(vec4 degrees) Konwersja stopni do radianów float degrees(float radians) vec2 degrees(vec2 radians) vec3 degrees(vec3 radians) vec4 degrees(vec4 radians) Aleksander Dawid 2001-2016 rok 205

Najważniejsze funkcje języka Shaderów Funkcje trygonometryczne Funkcja sinus float sin(float angle) vec2 sin(vec2 angle) vec3 sin(vec3 angle) vec4 sin(vec4 angle) Funkcja cosinus float cos(float angle) vec2 cos(vec2 angle) vec3 cos(vec3 angle) vec4 cos(vec4 angle) Aleksander Dawid 2001-2016 rok 206

Najważniejsze funkcje języka Shaderów Funkcje trygonometryczne Funkcja tangens float tan(float angle) vec2 tan(vec2 angle) vec3 tan(vec3 angle) vec4 tan(vec4 angle) Funkcja arcus sinus float asin(float x) vec2 asin(vec2 x) vec3 asin(vec3 x) vec4 asin(vec4 x) Aleksander Dawid 2001-2016 rok 207

Najważniejsze funkcje języka Shaderów Funkcje trygonometryczne Funkcja arcus cosinus float acos(float x) vec2 acos(vec2 x) vec3 acos(vec3 x) vec4 acos(vec4 x) Funkcja arcus tangens float atan(float y_over_x) vec2 atan(vec2 y_over_x) vec3 atan(vec3 y_over_x) vec4 atan(vec4 y_over_x) Aleksander Dawid 2001-2016 rok 208

Najważniejsze funkcje języka Shaderów Funkcje exponencjalne Funkcja potęgowa float pow(float x, float y) vec2 pow(vec2 x, vec2 y) vec3 pow(vec3 x, vec3 y) vec4 pow(vec4 x, vec4 y) Funkcja exponent e x float exp(float x) vec2 exp(vec2 x) vec3 exp(vec3 x) vec4 exp(vec4 x) Aleksander Dawid 2001-2016 rok 209

Najważniejsze funkcje języka Shaderów Funkcje exponencjalne Funkcja logarytm naturalny log e x float log(float x) vec2 log(vec2 x) vec3 log(vec3 x) vec4 log(vec4 x) Funkcja exponent 2 x float exp2(float x) vec2 exp2(vec2 x) vec3 exp2(vec3 x) vec4 exp2(vec4 x) Aleksander Dawid 2001-2016 rok 210

Najważniejsze funkcje języka Shaderów Funkcje exponencjalne Funkcja logarytm log 2 x float log2(float x) vec2 log2(vec2 x) vec3 log2(vec3 x) vec4 log2(vec4 x) Funkcja pierwiastkowania kwadratowego x float sqrt(float x) vec2 sqrt(vec2 x) vec3 sqrt(vec3 x) vec4 sqrt(vec4 x) Aleksander Dawid 2001-2016 rok 211

Najważniejsze funkcje języka Shaderów Funkcje exponencjalne Funkcja odwrotnego pierwiastka 1 x float inversesqrt(float x) vec2 inversesqrt(vec2 x) vec3 inversesqrt(vec3 x) vec4 inversesqrt(vec4 x) Aleksander Dawid 2001-2016 rok 212

Najważniejsze funkcje języka Shaderów Funkcje wspólne (zaokrągleń) Funkcja wartość bezwzględna float abs(float x) vec2 abs(vec2 x) vec3 abs(vec3 x) vec4 abs(vec4 x) Funkcja znakowa float sign(float x) vec2 sign(vec2 x) vec3 sign(vec3 x) vec4 sign(vec4 x) sign x = 1. 0 gdy x > 0 0. 0 gdy x = 0 1. 0 gdy x < 0 Aleksander Dawid 2001-2016 rok 213

Najważniejsze funkcje języka Shaderów Funkcje wspólne (zaokrągleń) Zaokrąglenie w dół do liczby całkowitej float floor(float x) vec2 floor(vec2 x) vec3 floor(vec3 x) vec4 floor(vec4 x) Zaokrąglenie w górę do liczby całkowitej float ceil(float x) vec2 ceil(vec2 x) vec3 ceil(vec3 x) vec4 ceil(vec4 x) Aleksander Dawid 2001-2016 rok 214

Najważniejsze funkcje języka Shaderów Funkcje wspólne (zaokrągleń) Część ułamkowa float fract(float x) vec2 fract(vec2 x) vec3 fract(vec3 x) vec4 fract(vec4 x) y = x floor(x) Modulo float mod(float x, float y) vec2 mod(vec2 x, vec2 y) vec3 mod(vec3 x, vec3 y) vec4 mod(vec4 x, vec4 y) Aleksander Dawid 2001-2016 rok 215

Najważniejsze funkcje języka Shaderów Funkcje wspólne (zaokrągleń) Minimum float min(float x, float y) vec2 min(vec2 x, vec2 y) vec3 min(vec3 x, vec3 y) vec4 min(vec4 x, vec4 y) Maximum float max(float x, float y) vec2 max(vec2 x, vec2 y) vec3 max(vec3 x, vec3 y) vec4 max(vec4 x, vec4 y) Aleksander Dawid 2001-2016 rok 216

Najważniejsze funkcje języka Shaderów Funkcje wspólne (zaokrągleń) Clamp (liczba z przedziału) float clamp(float x, float minval, float maxval) vec2 clamp(vec2 x, vec2 minval, vec2 maxval) vec3 clamp(vec3 x, vec3 minval, vec3 maxval) vec4 clamp(vec4 x, vec4 minval, vec4 maxval) Mieszanie liniowe float mix(float x, float y, float a) vec2 mix(vec2 x, vec2 y, float a) vec3 mix(vec3 x, vec3 y, float a) vec4 mix(vec4 x, vec4 y, float a) Aleksander Dawid 2001-2016 rok 217

Najważniejsze funkcje języka Shaderów Funkcje wspólne (zaokrągleń) Funkcja progowa float step(float edge, float x) vec2 step(vec2 edge, vec2 x) vec3 step(vec3 edge, vec3 x) vec4 step(vec4 edge, vec4 x) Funkcja gładka dla 0.0(edge0,edge1)1.0 float smoothstep(float edge0, float edge1, float x) vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x) vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x) vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x) Aleksander Dawid 2001-2016 rok 218

Najważniejsze funkcje języka Shaderów Funkcje geometryczne Funkcja długość wektora float length(float x) float length(vec2 x) float length(vec3 x) float length(vec4 x) L = x 2 + y 2 + z 2 + w 2 Funkcja odległości między dwoma punktami float distance(float p0, float p1) float distance(vec2 p0, vec2 p1) float distance(vec3 p0, vec3 p1) float distance(vec4 p0, vec4 p1) Aleksander Dawid 2001-2016 rok 219

Najważniejsze funkcje języka Shaderów Funkcje geometryczne Iloczyn skalarny wektorów float dot(float x, float y) float dot(vec2 x, vec2 y) float dot(vec3 x, vec3 y) float dot(vec4 x, vec4 y) v w = v w cos (α) Iloczyn wektorowy vec3 cross(vec3 x, vec3 y) v w = e x e y e z v x w x v y w y v z w z = (e x, e y, e z ) Aleksander Dawid 2001-2016 rok 220

Najważniejsze funkcje języka Shaderów Funkcje geometryczne Normalizacja wektora float normalize(float x) vec2 normalize(vec2 x) vec3 normalize(vec3 x) vec4 normalize(vec4 x) Rozpraszanie N x = 1 y 2 + z 2 + w 2 float faceforward(float N, float I, float Nref) vec2 faceforward(vec2 N, vec2 I, vec2 Nref) vec3 faceforward(vec3 N, vec3 I, vec3 Nref) vec4 faceforward(vec4 N, vec4 I, vec4 Nref) Aleksander Dawid 2001-2016 rok 221

Najważniejsze funkcje języka Shaderów Funkcje geometryczne Odbicie float reflect(float I, float N) vec2 reflect(vec2 I, vec2 N) vec3 reflect(vec3 I, vec3 N) vec4 reflect(vec4 I, vec4 N) Załamanie float refract(float I, float N, float eta) vec2 refract(vec2 I, vec2 N, float eta) vec3 refract(vec3 I, vec3 N, float eta) vec4 refract(vec4 I, vec4 N, float eta) Aleksander Dawid 2001-2016 rok 222

Najważniejsze funkcje języka Shaderów Funkcje macierzowe Mnożenie komponentów mat2 matrixcompmult(mat2 x, mat2 y) mat3 matrixcompmult(mat3 x, mat3 y) mat4 matrixcompmult(mat4 x, mat4 y) Aleksander Dawid 2001-2016 rok 223

Najważniejsze funkcje języka Shaderów Funkcje relacji wektorów Porównanie składowych wektora x[i]<y[i] bvec2 lessthan(vec2 x, vec2 y) bvec3 lessthan(vec3 x, vec3 y) bvec4 lessthan(vec4 x, vec4 y) Porównanie składowych wektora x[i]<=y[i] bvec2 lessthanequal(vec2 x, vec2 y) bvec3 lessthanequal(vec3 x, vec3 y) bvec4 lessthanequal(vec4 x, vec4 y) Aleksander Dawid 2001-2016 rok 224

Najważniejsze funkcje języka Shaderów Funkcje relacji wektorów Porównanie składowych wektora x[i]>y[i] bvec2 greaterthan(vec2 x, vec2 y) bvec3 greaterthan(vec3 x, vec3 y) bvec4 greaterthan(vec4 x, vec4 y) Porównanie składowych wektora x[i]>=y[i] bvec2 greaterthanequal(vec2 x, vec2 y) bvec3 greaterthanequal(vec3 x, vec3 y) bvec4 greaterthanequal(vec4 x, vec4 y) Aleksander Dawid 2001-2016 rok 225

Najważniejsze funkcje języka Shaderów Funkcje relacji wektorów Porównanie składowych wektora x[i]==y[i] bvec2 equal(vec2 x, vec2 y) bvec3 equal(vec3 x, vec3 y) bvec4 equal(vec4 x, vec4 y) Porównanie składowych wektora x[i]!=y[i] bvec2 notequal(vec2 x, vec2 y) bvec3 notequal(vec3 x, vec3 y) bvec4 notequal(vec4 x, vec4 y) Aleksander Dawid 2001-2016 rok 226

Najważniejsze funkcje języka Shaderów Funkcje relacji wektorów Prawda gdy którakolwiek ze składowych jest True bool any(bvec2 x) bool any(bvec3 x) bool any(bvec4 x) Prawda gdy wszystkie składowe zwracają prawdę bool all(bvec2 x) bool all(bvec3 x) bool all(bvec4 x) Aleksander Dawid 2001-2016 rok 227

Najważniejsze funkcje języka Shaderów Funkcja przeglądanie tekstur vec4 texture2d(sampler2d sampler, vec2 coord) vec4 texture2d(sampler2d sampler, vec2 coord, float bias) Funkcja zwraca kolor texela dla danej współrzędnej tekstury. Parametr bias dotyczy wybranej MIPMAPY Aleksander Dawid 2001-2016 rok 228

OpenCL Otwarty standard programowania multiprocesorów Aleksander Dawid programowanie procesorów graficznych

OpenCL Język tej biblioteki podobnie jak wszystkie systemy otwarte operuje na własnych typach zmiennych. cl_int, cl_float, cl_uint, cl_double, cl_long Aleksander Dawid programowanie procesorów graficznych

clgetplatformids clgetdeviceids clcreatecontext Strumień przetwarzania potoku OpenCL clcreatecommandqueue clcreateprogramwithsource Zwolnienie zasobów clbuildprogram clenqueuereadbuffer clcreatebuffer clenqueuendrangekernel clcreatekernel clsetkernelarg Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 1. Informacja o platformie i urządzaniach cl_int clgetplatformids(cl_uint nentries, cl_platform_id *platforms, cl_uint *nplatforms) nentries spodziewana ilość plaform platforms zwraca listę identyfikatorów platform OpenCL nplatforms zwraca ilość platform Sukces: CL_SUCCESS Porażka: CL_INVALID_VALUE cl_int clgetdeviceids(cl_platform_id platform, cl_device_type device_type, cl_uint nentries, cl_device_id *devices, cl_uint *ndevices) platform identyfikator platformy device_type CL_DEVICE_TYPE_CPU, CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_ALL nentries spodziwana ilość urządzeń devices zwraca listę identyfikatorów urządzeń. ndevices zwraca ilość urządzeń OpenCL Sukces: CL_SUCCESS Porażka: CL_INVALID_PLATFORM, CL_INVALID_DEVICE_TYPE, CL_INVALID_VALUE, CL_DEVICE_NOT_FOUND Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU cl_int clgetdeviceinfo(cl_device_id device, cl_device_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret) Device identyfikator urządzania Param_name nazwa parametru informacji Param_value_size rozmiar w bajtach parametru inforamcji Param_value wskaźnik do obszaru przechowującego informacje Param_value_size_ret zwrócony rozmiar Param_name CL_DEVICE_NAME CL_DEVICE_VENDOR CL_DEVICE_VERSION CL_DEVICE_MAX_CLOCK_FREQUENCY Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 2. Utworzenie kontekstu urządzenia cl_context clcreatecontext(cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void *pfn_notify ( const char *errinfo, const void *private_info, size_t cb, void *user_data), void *user_data, cl_int *errcode_ret) Zbiornik grupujący dane. properties właściwości platformy, NULL = domyślne num_devices zadeklarowana ilość urządzeń devices wskźnik do list urządzeń pfn_notify funkcja zwrotna (callback function) user_data związany z funkcja zwrotną errcode_ret zwraca kod błędu Sukces: CL_SUCCESS Porażka: CL_INVALID_PLATFORM, CL_INVALID_DEVICE, CL_INVALID_VALUE, Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 3. Utworzenie kolejkę poleceń na wybranym urządzeniu cl_command_queue clcreatecommandqueue(cl_context context, cl_device_id device, cl_command_queue_properties properties, cl_int *errcode_ret) context OpenCL kontext z poprzedniego kroku device identyfikator urządzenia properties właściwości kolejki poleceń errcode_ret zwraca kod błędu Sukces: CL_SUCCESS Porażka: CL_INVALID_CONTEXT, CL_INVALID_DEVICE, CL_INVALID_VALUE, CL_INVALID_QUEUE_PROPERTIES, CL_OUT_OF_HOST_MEMORY Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 4. Tworzenie obiektu programu dla kontekstu cl_program clcreateprogramwithsource (cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret) Context utworzony kontekst OpenCL Count ilość kontekstów Strings Ciąg z programem źródłowym kernela Lengths Długości każdego z ciągów errcode_ret zwracany kod błędu Sukces: CL_SUCCESS Porażka: CL_INVALID_CONTEXT, CL_INVALID_VALUE, CL_OUT_OF_HOST_MEMORY Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 5. Kompilacja programu cl_int clbuildprogram ( cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, void (*pfn_notify)(cl_program, void *user_data), void *user_data) program identyfikator programu num_devices ilość urządzeń device_list lista urządzeń Options wskaźnik do ciągu z opcjami (Optymalizacja) pfn_notify- funkcja zwrotna (callback function) user_data - związany z funkcja zwrotną Sukces: CL_SUCCESS Porażka: CL_INVALID_PROGRAM, CL_INVALID_VALUE, CL_INVALID_DEVICE, CL_COMPILER_NOT_AVAILABLE Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 6. Alokacja pamięci cl_mem clcreatebuffer ( cl_context context, cl_mem_flags flags, size_t size, void *host_ptr, cl_int *errcode_ret) context OpenCL kontekst flags pole bitowe specyfikujące sposób użycia pamięci CL_MEM_READ_WRITE, CL_MEM_WRITE_ONLY, CL_MEM_READ_ONLY, CL_MEM_USE_HOST_PTR CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR size rozmiar bufora do zaalokowania host_ptr wskaźnik(adres) tego bufora errcode_ret kod błędu Sukces: CL_SUCCESS Porażka: CL_INVALID_CONTEXT, CL_INVALID_BUFFER_SIZE, CL_INVALID_HOST_PTR, CL_MEM_OBJECT_ALLOCATION_FAILURE Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 7. Tworzenie kernela cl_kernel clcreatekernel ( cl_program program, const char *kernel_name, cl_int *errcode_ret) Program identyfikator programu kernel_name nazwa kernela errcode_ret zwracany kod błędu Sukces: CL_SUCCESS Porażka: CL_INVALID_PROGRAM, CL_INVALID_PROGRAM_EXECUTABLE, CL_INVALID_KERNEL_NAME, CL_INVALID_KERNEL_DEFINITION, CL_INVALID_VALUE Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 8. Ustawienie argumentów cl_int clsetkernelarg ( cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value) Kernel identyfikator kernela arg_index indeks argumentu arg_size rozmiar argumentu arg_value wskaźnik do bufora pamięci Sukces: CL_SUCCESS Porażka: CL_INVALID_KERNEL, CL_INVALID_ARG_INDEX, CL_INVALID_ARG_VALUE, CL_INVALID_MEM_OBJECT, CL_INVALID_ARG_SIZE Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 9. Uruchomienie kernela cl_int clenqueuendrangekernel ( cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t *global_work_offset, const size_t *global_work_size, const size_t *local_work_size, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event) command_queue kolejka poleceń Kernel kernel identyfikator work_dim ilość wymiarów określających zadanie global_work_offset na razie NULL, wprowadzony dla przyszłych wersji global_work_size lista określająca rozmiar dla każdego wymiaru local_work_size określa rozmiar grup roboczych num_events_in_wait_list określa zdarzenie na które musi czekać kernel event_wait_list - określa zdarzenie na które musi czekać kernel event identyfikator zdarzenia Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 9. Uruchomienie kernela cd Sukces: CL_SUCCESS Porażka: CL_INVALID_PROGRAM_EXECUTABLE, CL_INVALID_COMMAND_QUEUE, CL_INVALID_KERNEL, CL_INVALID_CONTEXT, CL_INVALID_KERNEL_ARGS, CL_INVALID_WORK_DIMENSION, CL_INVALID_WORK_GROUP_SIZE CL_INVALID_WORK_ITEM_SIZE, CL_INVALID_GLOBAL_OFFSET CL_OUT_OF_RESOURCES, CL_MEM_OBJECT_ALLOCATION_FAILURE, CL_INVALID_EVENT_WAIT_LIST, CL_OUT_OF_HOST_MEMORY Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 10. Odczytanie danych z urządzenia cl_int clenqueuereadbuffer ( cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, size_t cb, void *ptr, cl_uint num_events_in_wait_list, const cl_event *event_wait_list, cl_event *event) command_queue kolejka poleceń buffer identyfikator bufora blocking_read odczyt blokujący Offset przesunięcie w buforze cb ilość danych do odczytu ptr wskaźnik do bufora w pamięci gospodarza num_events_in_wait_list lista zdarzeń event_wait_list lista zdarzeń event - zdarzenie Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 10. Odczytanie danych z urządzenia cd Sukces: CL_SUCCESS Porażka: CL_INVALID_CONTEXT, CL_INVALID_COMMAND_QUEUE, CL_INVALID_MEM_OBJECT, CL_INVALID_VALUE, CL_INVALID_EVENT_WAIT_LIST, CL_MEM_OBJECT_ALLOCATION_FAILURE, CL_OUT_OF_HOST_MEMORY Aleksander Dawid programowanie procesorów graficznych

OpenCL - przygotowanie przetwarzania informacji na GPU 11. Zwolnienie zasobów status = clreleasekernel(kernel); status = clreleaseprogram(program); status = clreleasememobject(inputbuffer); status = clreleasememobject(outputbuffer); status = clreleasecommandqueue(commandqueue); status = clreleasecontext(context); Sukces: CL_SUCCESS Porażka: zależna od zwalnianego zasobów Aleksander Dawid programowanie procesorów graficznych

OpenCL - Kernel GPU kernel void helloworld( global char* in, global char* out) { int num = get_global_id(0); out[num] = in[num] + 1; } Aleksander Dawid programowanie procesorów graficznych

Platformy OpenCL AMD APP SDK 3.0 Karty AMD wspierane w OpenCL od wersji Radeon HD 4000 w górę AMD kompilacja kernel void helloworld( global char* in, global char* out) { int num = get_global_id(0); out[num] = in[num] + 1; } Aleksander Dawid programowanie procesorów graficznych

Platformy OpenCL CUDA TOOLKIT do wersji 4.0 Wspierane karty z rdzeniami CUDA od GF 8600GTX NVIDIA kompilacja kernel void helloworld( global char* in, global char* out) { int num = get_global_id(0); out[num] = in[num] + 1; } Aleksander Dawid programowanie procesorów graficznych

Przykład OpenCL na AMD i NVIDIA Kod CPU kernel void helloworld( global char* in, global char* out) { int num = get_global_id(0); out[num] = in[num] + 1; } Aleksander Dawid programowanie procesorów graficznych

Przykład OpenCL na AMD i NVIDIA Kod GPU kernel void helloworld( global char* in, global char* out) { int num = get_global_id(0); out[num] = in[num] + 1; } Aleksander Dawid programowanie procesorów graficznych

Programowanie procesorów graficznych NVIDIA (rdzenie CUDA)

Programowanie procesorów graficznych Wprowadzenie Procesory graficzne GPU (Graphics Processing Units) stosowane są w kartach graficznych do przetwarzania grafiki komputerowej i wyświetlania jej na ekranie monitora Motorem rozwoju GPU jest rynek gier komputerowych Fotorealizm w czasie rzeczywistym Cechy GPU Przetwarzanie równoległe Ilość rdzeni > 100 (1 CPU = 8 rdzeni) Przyspieszone operacje na macierzach. Wydajność rzędu Tfps Przetwarzanie wierzchołków i pixeli Przetwarzania światła Obsługa efektów fizycznych Obsługa biblioteki OpenGL i DirectX Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Naukowe obliczenia numeryczne 2 najszybsze komputery świata korzystają z kart graficznych do zwiększenia swojej mocy obliczeniowej. 1 Titan supercomputer Oak Ridge National Laboratory Układ Kepler GK110 2688 - rdzeni CUDA 6 GB pamięci GDDR5 384-bitowy interfejs 8,972 - GPU Tesla K20X (Architektura Kepler) Maksymalna moc obliczeniowa to 27 petaflops czyli 10 15 operacji zmiennoprzecinkowych na sekundę Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Naukowe obliczenia numeryczne 2 Tianhe 1a - Chiny TESLA (Fermi core) 448 CUDA Cores Tianhe 1a - Chiny 515 Gigaflops (podwójna precyzja) 14,336 procesorów Xeon X5670 1 Teraflop (pojedyncza precyzja) 7,168 GPU Nvidia Tesla M2050 Maksymalna wydajność 2.507 petaflops 10 15 operacji zmiennoprzecinkowych na sekundę Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Światowe zasoby Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Wzrost wydajności Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Wzrost wydajności Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Obliczenia ogólnego przeznaczenia na GPU Model Cg ( C for graphics) Obliczenia wykonywane były w ramach jednostek obliczeniowych pixel shader i vertex shader. Wynik obliczeń nie dało się odczytać bezpośrednio w postaci numerycznej tylko jako zestaw pixeli na ekranie monitora. Model CUDA (Compute Unified Device Architecture) Obliczenia wykonywane są na wszystkich dostępnych rdzeniach. Wynik obliczeń można odebrać w postaci numerycznej (terminal) Cechy CUDA Wielowątkowość Wielozadaniowość Programowanie w językach wysokiego poziomu Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Architektura CUDA Model pamięci Pamięć lokalna dostępna tylko dla wątku (bardzo szybka) Pamięć dzielona dostępna tylko dla wszystkich wątków w bloku (bardzo szybka) Pamięć globalna dostępna dla wszystkich wątków (raczej wolna). Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Architektura CUDA RAM CPU >= GPU Większa ilość pamięci na karcie zwiększa prędkość obliczeń Wspierane języki programowania. Dodatkowo istniej możliwość programowania CUDA w językach JAVA i Python Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Programowanie CUDA C Kompilator: nvcc Dostęþny jest w pakiecie CUDA toolkit dla różnych systemów operacyjnych takich jak Windows, Linux, Mac. Pełne wsparcie dla standardu ANSI C z elementami C++ CUDA w wersji 1.0 dostępne jest już dla kart NVIDA GeForce 8600 Kod programu Kod CPU Kod GPU Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Programowanie CUDA C Zadania Kod CPU Informacja o sprzęcie Inicjalizacja pamięci Operacje I/O CPU->GPU, GPU->CPU Zwalnianie pamięci Zadania Kod GPU Sterowanie programem Pamięci lokalne i dzielone Obliczenia numeryczne Synchronizacja wątków Program oddaje sterowanie do GPU i czeka na wynik obliczeń. Wykonane może to być w sposób synchroniczny lub asynchroniczny. GPU rozwiązuje zadanie na wszystkich dostępnych rdzeniach równolegle. Kod programu musi być specjalnie urównoleglony. Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Programowanie CUDA C Wymagania systemowe Windows XP/VISTA/7/8/10 CUDA developer driver, CUDA toolkit, MS Visual Studio C++ Linux: nowsze dystrybucje. CUDA developer driver, CUDA toolkit, gcc4.4 Dodatkowo dla wszystkich systemów GPUComputingSDK, w którym są przykłady programów CUDA. Działanie tych programów jest gwarancją prawidłowej instalacji sterowników CUDA w systemie. Uwaga!!! WINDOWS VISTA/7 resetuje karte po braku odpowiedzi w przeciągu 90 s. Warto ten czas przedłużyć gdy nie będziemy korzystać z grafiki. Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod CPU (informacja o zainstalowanej karcie) #include <stdio.h> #include <cutil.h> W pliku nagłówkowym cutil.h zawarte są informacje o wszystkich nagłówkach CUDA. Aby zastosować tą funkcje w systemi musi być dostępna biblioteka libcutil_x86_64.a (Linux64), która znajduje się w GPUComputingSDK. void PrintDevicesInformation() { int devicecount,nrdev,nmulproc; cudagetdevicecount(&devicecount); printf("number of CUDA devices: %d\n",devicecount); for(nrdev = 0; nrdev < devicecount; nrdev++) { cudadeviceprop deviceprop; cudagetdeviceproperties(&deviceprop, nrdev); printf("device %d: %s\n", nrdev, deviceprop.name); printf("maxthreadsperblock: %d\n", deviceprop.maxthreadsperblock); nmulproc=deviceprop.multiprocessorcount; printf("multiprocessorcount: %d\n", nmulproc); printf("computemode: %d\n", deviceprop.computemode); printf("sharedmemperblock: %ld\n", deviceprop.sharedmemperblock); } } Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Pola struktury cudadeviceprop int canmaphostmemory // Urządzenie pozwala na mapowanie pamięci RAM int clockrate // Częstotliwość zegara w khz int computemode // cudacomputemodedefault - przetwarzanie wielowątkowe załączone // cudacomputemodeexclusive tylko jeden wątek // cudacomputemodeprohibited żaden wątek (CUDA wyłaczone) int concurrentkernels // Urządzenie uruchamia wiele jąder (kernel) konkurencyjnie int deviceoverlap // Urządzenie konkurencyjnie kopiuje i wykonuje jądra. int ECCEnabled // Urządzenie wspiera ECC int integrated // Czy urządzenie jest zintegrowane int kernelexectimeoutenabled // Czy są ogranicznia czasowe na wykonanie kernela int major // Główna wspierana wersja CUDA Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Pola struktury cudadeviceprop int maxgridsize [3] // Maksymalny rozmiar macierzy obliczeniowej w każdym kierunku dim1 x dim2 x dim3 int maxtexture1d // Maksymalny rozmiar tekstury jednowymiarowej int maxtexture2d [2] // Maksymalny rozmiar tekstury dwuwymiarowej int maxtexture2darray [3] // Maksymalny rozmiar macierzy tekstury dwuwymiarowej int maxtexture3d [3] // Maksymalny rozmiar tekstury trójwymiarowej int maxthreadsdim [3] // Maksymalny rozmiar każdego wymiaru w bloku wątków int maxthreadsperblock // Maksymalna ilość wątków w bloku size_t mempitch // Maksymalny rozmiar pakietu w bajtach dozwolony przy kopiowaniu int minor // Numer 1.x wersji CUDA wspieranej Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Pola struktury cudadeviceprop int multiprocessorcount // Ilość multiprocesorów w urządzeniu char name [256] // Ciąg ASCI identyfikujący urządzenie int pcibusid // Identyfikator PCI Bus urządzenia int pcideviceid // PCI ID urządzenia int regsperblock // ilość rejestrów 32-bit na blok size_t sharedmemperblock // Pamięć dzielona dostępna na blok [bajty] size_t surfacealignment // Wymagania dotyczące wyrównania powierzchni int tccdriver // 1 Jeżeli TESLA używa sterownika TCC; w przeciwnym razie 0 size_t texturealignment // Wymagania dotyczące wyrównania tekstury size_t totalconstmem // Constan memory dostępna na urządzeniu w bajtach size_t totalglobalmem // Globalna pamięć dostępna na urządzeniu int warpsize // Wielkość Warp w wątkach Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod CPU (informacja o zainstalowanej karcie) int main(int argc, char* argv[]) { PrintDevicesInformation(); return 0; } Kompilacja gcc4.4 UBUNTU > nvcc program.cu -lcudart pathtolib/libcutil_x86_64.a -o program Wynik działania Number of CUDA devices: 1 Device 0: Quadro FX 5800 maxthreadsperblock: 512 multiprocessorcount: 30 computemode: 0 sharedmemperblock: 16384 Często stosowane rozszerzenie.cu zarówno w Linux jak i w Windows Aleksander Dawid 2010-2016

Kwalifikatory Typy funkcji host - oznacza funkcję która będzie wykonywana na CPU device - oznacza że funkcja będzie wykonywana na GPU global -funkcja globalna, wywoływana z CPU(host) i GPU(device) CUDA 3.x host device host device func() { #if CUDA_ARCH >= 500 // Device code path for compute capability 5.x #elif CUDA_ARCH >= 300 // Device code path for compute capability 3.x #elif CUDA_ARCH >= 200 // Device code path for compute capability 2.x #elif!defined( CUDA_ARCH ) // Host code path #endif } Aleksander Dawid 2010-2016

Kwalifikatory Typy zmiennych constant - oznacza stałą zadeklarowaną w GPU device - oznacza zmienną wewnątrz GPU shared - razem z kwalifikatorem device oznacza zmienną która rezyduje w pamięci dzielonej bloku i istnieje tak długo jak istnieje blok. Dostępna jest tylko dla wątków z bloku. Aleksander Dawid 2010-2016

Zarządzanie urządzeniami Wybór urządzenia najlepiej odpowiadającego wymaganiom obliczeniowym host cudaerror_t cudachoosedevice ( int* device, const cudadeviceprop* prop ) device urządzenie wybrane do obliczeń prop wymagania względem urządzenia. Returns cudasuccess, cudaerrorinvalidvalue Liczba dostępnych urządzeń CUDA host device cudaerror_t cudagetdevicecount ( int* count ) count liczba dostępnych urządzeń CUDA Aleksander Dawid 2010-2016

Zarządzanie urządzeniami Funkcja zwraca urządzenie id urządzenia na którym trwają obliczenia. host device cudaerror_t cudagetdevice ( int* device ) device urządzenie wybrane do obliczeń Ustawienie urządzenia na którym będą wykonywane obliczenia. host cudaerror_t cudasetdevice (int device) device urządzenie wybrane do obliczeń Resetowanie wszystkich ustawień w urządzeniu, zamykanie wątków obliczeniowych. host cudaerror_t cudadevicereset (void) Aleksander Dawid 2010-2016

Zarządzanie urządzeniami Czekaj aż wszystkie urządzenia przestaną liczyć. host device cudaerror_t cudadevicesynchronize ( void ) Ustaw flagę urządzenia host cudaerror_t cudasetdeviceflags ( unsigned int flags ) flags wskaźnik do ustawionej flagi na komputerze. Pobierz flagę urządzenia host cudaerror_t cudagetdeviceflags ( unsigned int* flags ) flags wskaźnik do ustawionej flagi na komputerze. Aleksander Dawid 2010-2016

Obsługa błędów Zwracanie nazwy błędu w postaci ciągu znaków. host device const char* cudageterrorname ( cudaerror_t error ) error identyfikator błędu. Zwracanie opisu błędu w postaci ciągu znaków. host device const char* cudageterrorstring ( cudaerror_t error ) error identyfikator błędu. Funkcja zwraca numer ostatniego błędu host device cudaerror_t cudagetlasterror ( void ) Aleksander Dawid 2010-2016

Obsługa zdarzeń (Event Management) Utwórz obiekt zdarzenie host cudaerror_t cudaeventcreate ( cudaevent_t* event ) event obiekt zdarzenie. Utwórz obiekt zdarzenie i ustaw dla niego flagę. host device cudaerror_t cudaeventcreatewithflags ( cudaevent_t* event, unsigned int flags ) Usuń obiekt zdarzenie host device cudaerror_t cudaeventdestroy ( cudaevent_t event ) Aleksander Dawid 2010-2016

Obsługa zdarzeń (Event Management) Oblicz czas pozostały pomiędzy zdarzeniami host cudaerror_t cudaeventelapsedtime ( float* ms, cudaevent_t start, cudaevent_t end ) Prześlij status zdarzenia host cudaerror_t cudaeventquery ( cudaevent_t event ) Nagraj zdarzenie host device cudaerror_t cudaeventrecord ( cudaevent_t event, cudastream_t stream = 0 ) Czekaj dopuki jakieś zdarzenie się wydarzy host cudaerror_t cudaeventsynchronize ( cudaevent_t event ) Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod CPU (CPU->GPU) #define real float real* R; size_t size; void CPUMemAlloc() { size = 16*sizeof(real); // 16 liczb typu real R = (real*)malloc(size); memset(r,0,size); } Funkcja CPUMemAlloc alokuje pamięć dla 16 liczb typu real czyli float real* d_r; void GPUMemAlloc() { cudamalloc((void**)&d_r, size); } Funkcja GPUMemAlloc alokuje pamięć na karcie graficznej dla 16 liczb typu real Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod CPU (CPU->GPU) void CopyCPUToGPU() { cudamemcpy(d_r, R, size, cudamemcpyhosttodevice); } Funkcja kopiuje size bloków pamięci z komputera na kartę graficzną Host komputer z CPU Device karta graficzna void CopyGPUToCPU() { cudamemcpy(r, d_r, size, cudamemcpydevicetohost); } Odwrotna operacja W operacjach tych brakuje obsługi wyjątków, które mogą wystąpić z różnych przyczyn. Funkcja cudagetlasterror()podaje numer ostatniego błędu. Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod CPU (CPU->GPU) int main(int argc, char* argv[]) { CPUMemAlloc(); GPUMemAlloc(); R[0]=5; CopyCPUToGPU(); CopyGPUToCPU(); printf("r[0]=%f\n",r[0]); return 0; } Brakuje operacji wykonywanych na karcie graficznej Musimy stworzyć tzw. Kernel, który będzie wykonywany na GPU. Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod CPU (Inicjalizacja Kernela GPU) int threadsperblock, blockspergrid, sharedsize; void InitKernel() { threadsperblock = 16; //Tyle samo wątków w bloku ile liczb mamy do //przeliczenia blockspergrid = 1; sharedsize = size; //Szybka pamięć dzielona na 16 liczb real } Każda karta graficzna ma inną maksymalną ilość wątków w jednym bloku. Wartość ta waha się między 128 a 1024. Tutaj blok został ustalony na 16 wątków. Ilość bloków w macierzy obliczeniowej też zależy od karty, tutaj ustalamy 1 blok. Teraz możemy już pisać program dla GPU Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod GPU (Przemnożenie macierzy przez dwa) global void MultByTwo(real* R){ extern shared real rs[]; unsigned int id = threadidx.x; R[id]=R[id]*2; } Główna procedura w GPU tworzona jest przez dyrektywę global. shared oznacza pamięć dostępną dla całego bloku. int main(int argc, char* argv[]) { CPUMemAlloc(); GPUMemAlloc(); R[0]=5; CopyCPUToGPU(); InitKernel(); MultByTwo<<<blocksPerGrid, threadsperblock, sharedsize>>>(d_r); CopyGPUToCPU(); printf( R[0]=%f\n,R[0]); return 0; } Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Przetwarzanie Kod sekwencyjny Wielokrotne wywoływanie kodu równoległego dla tego samego zestawu danych Kod równoległy kernel0<<<>>>() Kod sekwencyjny Kod równoległy kernel1<<<>>>() Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod GPU (Sumowanie elementów macierzy) global void SumM(real* R){ extern shared real rs[]; unsigned int id = threadidx.x; rs[id]=r[id]; syncthreads(); if(id==0){ real SUM=0; for(int i=0;i<16;i++){ SUM+=rS[i]; } R[0]=SUM; } } int main(int argc, char* argv[]) { CPUMemAlloc(); GPUMemAlloc(); R[0]=5;R[1]=2;R[2]=4; CopyCPUToGPU(); InitKernel(); SumM<<<blocksPerGrid, threadsperblock, sharedsize>>>(d_r); CopyGPUToCPU(); printf( R[0]=%f\n,R[0]); return 0; } Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod GPU (Redukcja 1) W poprzednim programie do sumowania liczb z każdego wątku użyte został tylko jeden wątek o identyfikatorze 0 global void SumReducto(real* R){ extern shared real rs[]; unsigned int id = threadidx.x; rs[id]=r[id]; syncthreads(); for(unsigned int s=1; s < blockdim.x; s *= 2) { if (id % (2*s) == 0) { rs[id] += rs[id + s]; } syncthreads(); } if(id == 0) R[0] = rs[0]; } Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod GPU (Redukcja 1) Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod GPU (Redukcja 2) Operacja modulo (%) jest bardzo wolna i wymaga zmiany. global void SumReducto2(real* R){ extern shared real rs[]; unsigned int id = threadidx.x; rs[id]=r[id]; syncthreads(); for(unsigned int s=1; s < blockdim.x; s *= 2) { int index = 2 * s * id; if (index < blockdim.x) { rs[index] += rs[index + s]; } syncthreads(); } if(id == 0) R[0] = rs[0]; } Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod GPU (Obliczanie numeryczne całki metoda trapezów) Polega na sumowaniu pól trapezów pod krzywą Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod GPU (Obliczanie numeryczne całki metoda trapezów) global void Trapez(real* Y, real* R){ extern shared real rs[]; unsigned int id = threadidx.x; rs[id]=y[id]; syncthreads(); if(id<blockdim.x-1){ real field; field=(rs[id] + 0.5* abs(rs[id]-rs[id+1]))*dxgpu; syncthreads(); rs[id]=field; } for(unsigned int s=1; s < blockdim.x; s *= 2) { int index = 2 * s * id; if (index < blockdim.x) { rs[index] += rs[index + s]; } syncthreads(); } if(id == 0) R[0] = rs[0]; } Aleksander Dawid 2010-2016

Programowanie procesorów graficznych Kod GPU (Obliczanie numeryczne całki metoda trapezów) constant real dxgpu=0; int main(int argc, char* argv[]) { CPUMemAlloc(); GPUMemAlloc(); InitKernel(); // threadsperblock=128 dx=0.0078125; //1/128 cudamemcpytosymbol(dxgpu, &dx, sizeof(real)); for(int i=0;i<threadsperblock;i++){ Y[i]=sqrt(1-(i*dx)*(i*dx)); } CopyCPUToGPU(); Trapez<<<blocksPerGrid, threadsperblock, sharedsize>>>(d_y, d_r); CopyGPUToCPU(); printf( R[0]=%f\n,R[0]); return 0; } Aleksander Dawid 2010-2016

Aleksander Dawid 290 CUDA-Układ wielu cząstek Numeryczne rozwiązywanie równań ruchu bazuje na rozwinięciu szeregu Taylora wokół pewnej chwili czasowej. Postać ogólna szeregu Taylora i j

Aleksander Dawid 291 Układ wielu cząstek Śledzenie trajektorii cząstki w odpowiednich przedziałach czasowych Algorytm velocity Verlet

V Ar-Ar [10-21 J] Układ wielu cząstek Potencjał Lennarda-Jonesa 2 1 0-1 Parametry zależne od typu atomu -2 2 4 6 8 10 12 14 16 r [A] Siły - potencjł symetryczny Aleksander Dawid 292

Aleksander Dawid 293 Siłę liczymy jako gradient potencjału. Siła jest wektorem o 3 składowych F(x,y,z) Obliczanie siły - Gradient potencjału Lennarda-Jonesa

Aleksander Dawid 294 Obliczanie siły kod sekwencyj for(i=0;i<n-1;i++) //F[i],R[i] struktury przechowujące { // siły i położenia poszczególnych for(j=i+1;j<n;j++) // atomów { Rxij=R[i].x - R[j].x; Ryij=R[i].y - R[j].y; Rzij=R[i].z - R[j].z; Rijsqr2 = Rxij*Rxij + Ryij*Ryij + Rzij*Rzij; Rij = sqrt(rijsqr2); Rijs2 = (Sigma*Sigma)/Rijsqr2; Rijap = Rijs2*Rijs2*Rijs2; Rijrp = 2*Rijs2*Rijs2*Rijs2*Rijs2*Rijs2*Rijs2; FXij = (ALJ*Rxij*(Rijrp-Rijap))/Rijsqr2; FYij = (ALJ*Ryij*(Rijrp-Rijap))/Rijsqr2; FZij = (ALJ*Rzij*(Rijrp-Rijap))/Rijsqr2; FXji = -FXij; FYji = -FYij; FZji = -FZij; F[i].x += FXij; F[i].y += FYij; F[i].z += FZij; F[j].x += FXji; F[j].y += FYji; F[j].z += FZji; } }

Aleksander Dawid 295 Obliczanie siły kod CUDA global void Force(real4* Rvect,real4* Fvect) { extern shared real4 rpos[]; //Pamięć dzielona unsigned int gid = mul24(blockdim.x,blockidx.x) + threadidx.x; if(gid>gn) return; int i,tile; real4 mpos; real3 f=make_real3(0.0f,0.0f,0.0f); mpos=rvect[gid]; for (i = 0, tile = 0; i < gn; i += gp, tile++) { int bli = tile * blockdim.x; int idx = bli + threadidx.x; //kopiowania porcji położeń do pamięci dzielonej rpos[threadidx.x] = Rvect[idx]; syncthreads(); f=calcforcetail(bli,gid,mpos,f); syncthreads(); } // Zapis siły w zmiennej globalnej Fvect[gid]=make_real4(f.x,f.y,f.z,0.0f); }

Aleksander Dawid 296 Obliczanie siły kod CUDA Obliczanie siły na i-te centrum odziaływania 256 wątków 256 wątków 256 wątków Kopiuj położenia Pamięć dzielona Przesuń do następnego bloku Oblicz w pojedynczym wątku odległość między i-tym atomem a położeniemi atomów zapisanym w pamięci dzielonej bloku.

Aleksander Dawid 297 Obliczanie siły- sumowanie par w pamięci dzielonej device real3 CalcForceTail(int bli,unsigned int gbli,real4 r,real3 f) { int i; extern shared real4 rpos[]; for(i=0;i<blockdim.x;i++){ } return f; } if( bli+i!= gbli){ f=calcpairs(r, rpos[i], f); }

Aleksander Dawid 298 Obliczanie siły między i-tym a j-tym atomem device real3 CalcPairs(real4 ri, real4 rj, real3 f) { real R2S,InvR2, Rijap,Rijrp,RP; real4 Rij; Rij.x = ri.x - rj.x; Rij.y = ri.y - rj.y; Rij.z = ri.z - rj.z; Rij.w = Rij.x*Rij.x + Rij.y*Rij.y + Rij.z*Rij.z; InvR2=1.0f/Rij.w; R2S=SGM2*InvR2; Rijap=R2S*R2S*R2S; Rijrp=2*Rijap*Rijap; RP=EPS24*(Rijrp-Rijap)*InvR2; f.x += RP*Rij.x; f.y += RP*Rij.y; f.z += RP*Rij.z; return f; }

Aleksander Dawid 299 Rozwiązywanie równań ruch (algorytm Velocity Verlet) Aby nie składowąć starych przyspieszeń, algorytm dzieli się na dwa kroki global void IntegrateHalf(real4* Rvect,real4* Vvect,real4* Fvect) { int idx = mul24(blockdim.x,blockidx.x) + threadidx.x; if(idx>gn) return; real4 dr; real3 f=make_real3(fvect[idx].x,fvect[idx].y,fvect[idx].z); real3 v=make_real3(vvect[idx].x,vvect[idx].y,vvect[idx].z); real3 r=make_real3(rvect[idx].x,rvect[idx].y,rvect[idx].z); dr.x = v.x*gdt + f.x*gimass*gdt; dr.y = v.y*gdt + f.y*gimass*gdt; dr.z = v.z*gdt + f.z*gimass*gdt; r.x += dr.x; r.y += dr.y; r.z += dr.z; v.x += f.x*gimass; v.y += f.y*gimass; v.z += f.z*gimass; Rvect[idx]=make_real4(r.x,r.y,r.z,0.0f); Vvect[idx]=make_real4(v.x,v.y,v.z,0.0f); syncthreads(); }

Aleksander Dawid 300 Rozwiązywanie równań ruch (algorytm Velocity Verlet) Aby nie składowąć starych przyspieszeń, algorytm dzieli się na dwa kroki global void IntegrateFull(real4* Vvect,real4* Fvect) { unsigned int idx = mul24(blockdim.x,blockidx.x) + threadidx.x; if(idx>gn) return; real3 f=make_real3(fvect[idx].x,fvect[idx].y,fvect[idx].z); real3 v=make_real3(vvect[idx].x,vvect[idx].y,vvect[idx].z); v.x += f.x*gimass; v.y += f.y*gimass; v.z += f.z*gimass; Vvect[idx]=make_real4(v.x,v.y,v.z,1.0f); }

Aleksander Dawid 301 Rozwiązywanie równań ruch (algorytm Velocity Verlet) t Położenia początkowe t+δt Nowe położenia Każdy atom skojarzony jest z jednym wątkiem Cząstka jest jednostką obliczeniową

Aleksander Dawid 302 Rozwiązywanie równań ruch (algorytm Velocity Verlet) //Inicjalizacja for(t=0;t<time;t++) { IntegrateHalf<<<blocksPerGrid,threadsPerBlock,sharedSize>>>(d_R,d_V,d_F); Force<<<blocksPerGrid, threadsperblock, sharedsize>>>(d_r,d_f); IntegrateFull<<<blocksPerGrid, threadsperblock, sharedsize>>>(d_v,d_f); ReadTrajectory<<<blocksPerGrid, threadsperblock>>>(d_r,d_traj,item); item+=n; }

Aleksander Dawid 303 Zapis trajektorii do bufora w pamięci globalnej global void ReadTrajectory(real4* Rvect,real4* Traj, int item) { unsigned int idx = mul24(blockdim.x,blockidx.x) + threadidx.x; if(idx>gn) return; real3 r=make_real3(rvect[idx].x,rvect[idx].y,rvect[idx].z); } Traj[item+idx]=make_real4(r.x,r.y,r.z,idx);

Stabilność numeryczna Aleksander Dawid 304

Przyśpieszenie w stosunku do CPU dla liczb podwójnej precyzji Aleksander Dawid 305

Niektóre wyniki Aleksander Dawid 306

Programowanie procesorów graficznych NEXT TECHNOLOGY Aleksander Dawid programowanie procesorów graficznych