Centralny procesor (CPU) komputera i procesor graficzny (GPU) współdziałają w każdym momencie korzystania z komputera w celu zapewnienia wyraźnego i elastycznego interfejsu graficznego. Czytaj dalej, aby lepiej zrozumieć, jak działają razem.
zdjęcie zrobione przez sskennel.
Dzisiejsza sesja pytań i odpowiedzi przychodzi do nas dzięki uprzejmości SuperUser - poddziału Stack Exchange, grupy dyskusyjnej poświęconej tematyce społecznościowej.
Czytnik SuperUser Sathya zadał pytanie:
Tutaj możesz zobaczyć zrzut ekranu małego programu C ++ o nazwie Triangle.exe z obrotowym trójkątem opartym na OpenGL API.
Jest to wprawdzie bardzo prosty przykład, ale myślę, że można go zastosować do innych operacji kart graficznych.
Byłem po prostu ciekawy i chciałem poznać cały proces od dwukrotnego kliknięcia na Triangle.exe w Windows XP, aż zobaczyłem trójkąt obracający się na monitorze. Co się dzieje, w jaki sposób CPU (który najpierw obsługuje .exe) i GPU (który ostatecznie wyprowadza trójkąt na ekranie) współdziałają?
Wydaje mi się, że udział w wyświetlaniu tego obracającego się trójkąta to przede wszystkim następujący sprzęt / oprogramowanie, między innymi:
Sprzęt komputerowy
Oprogramowanie
Czy ktoś może wyjaśnić proces, może z jakimś schematem do ilustracji?
Nie powinno to być skomplikowanym wyjaśnieniem, które obejmuje każdy pojedynczy krok (chyba, że wykracza poza zakres), ale wyjaśnienie, które może wykonać pośredni informatyk.
Jestem prawie pewna, że wielu ludzi, którzy nazwaliby siebie fachowcami IT, nie potrafiłoby poprawnie opisać tego procesu.
Chociaż wielu członków społeczności odpowiedziało na to pytanie, Oliver Salzburg zrobił jeszcze więcej i odpowiedział na nie nie tylko szczegółową odpowiedzią, ale także doskonałą grafiką towarzyszącą.
Obraz JasonC, dostępny jako tapeta tutaj.
On pisze:
Postanowiłem napisać nieco o aspekcie programowania i o tym, jak komponenty ze sobą rozmawiają. Może rzuci trochę światła na pewne obszary.
Co trzeba zrobić, aby uzyskać pojedynczy obraz, który zamieściłeś w swoim tekście, narysowany na ekranie?
Istnieje wiele sposobów narysowania trójkąta na ekranie. Dla uproszczenia załóżmy, że nie użyto buforów wierzchołków. (ZA bufor wierzchołkówjest obszarem pamięci, w którym przechowuje się współrzędne.) Załóżmy, że program po prostu powiedział rurociągowi przetwarzania grafiki o każdym pojedynczym wierzchołku (wierzchołek jest po prostu współrzędną w przestrzeni) z rzędu.
Ale, zanim będziemy mogli cokolwiek rysować, najpierw musimy uruchomić rusztowanie. Zobaczymy czemu później:
// Wyczyść ekran i bufor głębi glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Resetuj bieżącą matrycę widoku modelu glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Rysowanie za pomocą trójkątów glBegin (GL_TRIANGLES); // Red glColor3f (1.0f, 0.0f, 0.0f); // Top Of Triangle (Front) glVertex3f (0.0f, 1.0f, 0.0f); // Zielony glColor3f (0.0f, 1.0f, 0.0f); // Left Of Triangle (Front) glVertex3f (-1.0f, -1.0f, 1.0f); // Blue glColor3f (0.0f, 0.0f, 1.0f); // Right of Triangle (Front) glVertex3f (1.0f, -1.0f, 1.0f); // Wykonano rysunek glEnd ();
Kiedy piszesz program, który chce korzystać z karty graficznej, zwykle wybierasz jakiś rodzaj interfejsu do sterownika. Niektóre dobrze znane interfejsy do sterownika to:
W tym przykładzie będziemy trzymać się OpenGL. Teraz twój interfejs do sterownika jest tym, co daje ci wszystkie narzędzia potrzebne do stworzenia twojego programu rozmowa do karty graficznej (lub sterownika, który wtedy rozmowy do karty).
Ten interfejs z pewnością da ci pewność przybory. Narzędzia te mają postać interfejsu API, który można wywołać z poziomu programu.
To API jest używane w powyższym przykładzie. Przyjrzyjmy się bliżej.
Zanim naprawdę możesz wykonać dowolny rysunek, musisz wykonać Ustawiać. Musisz zdefiniować swój widok (obszar, który będzie faktycznie renderowany), twoją perspektywę ( aparat fotograficzny do twojego świata), jakiego antyaliasingu użyjesz (aby wygładzić krawędź twojego trójkąta) ...
Ale nie będziemy na to patrzeć. Rzucimy okiem na rzeczy, które będziesz musiał zrobić każda rama. Lubić:
Czyszczenie ekranu
Rurka graficzna nie wyczyści ekranu dla ciebie w każdej klatce. Musisz to powiedzieć. Czemu? Dlatego:
Jeśli nie wyczyścisz ekranu, po prostu zremisować to każda klatka. Dlatego dzwonimy glClear
zGL_COLOR_BUFFER_BIT
zestaw. Drugi bit (GL_DEPTH_BUFFER_BIT
) mówi OpenGL, aby wyczyścić głębokośćbufor. Ten bufor służy do określenia, które piksele znajdują się z przodu (lub z tyłu) innych pikseli.
Transformacja
Źródło obrazu
Transformacja to część, w której przyjmujemy wszystkie współrzędne wejściowe (wierzchołki naszego trójkąta) i stosujemy naszą matrycę ModelView. To jest matryca, która wyjaśnia jak nasz Model (wierzchołki) są obracane, skalowane i tłumaczone (przesuwane).
Następnie stosujemy naszą macierz projekcyjną. Spowoduje to przesunięcie wszystkich współrzędnych w taki sposób, aby prawidłowo ustawiały się one względem naszego aparatu.
Teraz przekształcamy się jeszcze raz dzięki naszej macierzy rzutni. Robimy to, aby skalować nasze Model do wielkości naszego monitora. Teraz mamy zestaw wierzchołków, które są gotowe do renderowania!
Wrócimy do transformacji nieco później.
Rysunek
Aby narysować trójkąt, możemy po prostu powiedzieć OpenGL, aby rozpocząć nowy lista trójkątów poprzez dzwonienie glBegin
z GL_TRIANGLES
stały.
Istnieją również inne formularze, które możesz narysować. Jak trójkątny pasek lub trójkątny wachlarz. Są to przede wszystkim optymalizacje, ponieważ wymagają mniejszej komunikacji pomiędzy procesorem a GPU w celu narysowania takiej samej liczby trójkątów.
Następnie możemy dostarczyć listę zestawów 3 wierzchołków, które powinny stanowić każdy trójkąt. Każdy trójkąt używa 3 współrzędnych (tak jak w przestrzeni 3D). Dodatkowo zapewniam również kolor dla każdego wierzchołka, przez wywołanieglColor3f
przed powołanie glVertex3f
.
Cień między 3 wierzchołkami (3 rogi trójkąta) jest obliczany przez OpenGLautomatycznie. Będzie interpolować kolor na całej powierzchni wielokąta.
Teraz, gdy klikniesz okno. Aplikacja musi jedynie przechwytywać komunikat okna, który sygnalizuje kliknięcie. Następnie możesz uruchomić dowolną akcję w swoim programie.
To dostaje a los trudniejsze, gdy chcesz rozpocząć interakcję ze sceną 3D.
Najpierw musisz dokładnie wiedzieć, w którym pikselu użytkownik kliknął okno. Następnie biorąc swoje perspektywicznybiorąc pod uwagę, możesz obliczyć kierunek promienia, od punktu kliknięcia myszą w scenie. Następnie możesz obliczyć, czy jakikolwiek obiekt w twojej scenie przecina się z tym promieniem. Teraz wiesz, czy użytkownik kliknął obiekt.
Jak to zrobić, żeby się obracał?
Znam dwa rodzaje transformacji, które są generalnie stosowane:
Różnica polega na tym kości wpływają na pojedyncze wierzchołki. Matryce zawsze działają w ten sam sposób na wszystkie narysowane wierzchołki. Spójrzmy na przykład.
Przykład
Wcześniej załadowaliśmy nasze macierz jednostkowa przed rysowaniem naszego trójkąta. Macierz tożsamości to taka, która po prostu zapewnia bez transformacji w ogóle. Cokolwiek rysuję, zależy tylko od mojej perspektywy. Tak więc trójkąt nie zostanie w ogóle obrócony.
Jeśli chcę go teraz obrócić, mógłbym sam zrobić matematykę (na CPU) i po prostu zadzwonić glVertex3f
zinny współrzędne (które są obrócone). Albo mogę pozwolić GPU wykonać całą pracę, dzwoniąc glRotatef
przed rysowaniem:
// Obróć trójkąt na osi Y glRotatef (ilość, 0.0f, 1.0f, 0.0f);
ilość
jest oczywiście tylko stałą wartością. Jeśli chcesz animować, będziesz musiał śledzić ilość
i zwiększ to każdą klatkę.
W tym prostym przykładzie nie musimy dbać o matryce. Po prostu dzwonimy glRotatef
i troszczy się o to wszystko dla nas.
glRotate
wytwarza obrótkąt
stopnie wokół wektora x y z. Bieżąca macierz (seeglMatrixMode) jest mnożona przez macierz rotacji z produktem zastępującym bieżącą macierz, tak jak wywołano metodę ifglMultMatrix z następującą macierzą jako argumentem:x 2 1 - c + cx y 1 - c - z sx z 1 - c + y s 0 y x 1 - c + z sy 2 1 - c + cy z 1 - c - x s 0 x z 1 - c - y sy z 1 - c + x sz 2 1 - c + c 0 0 0 0 1
Cóż, dziękuję za to!
Oczywistym jest, że dużo się mówi do OpenGL. Ale to nie mówi nas byle co. Gdzie jest komunikacja?
Jedyne, co OpenGL nam w tym przykładzie mówi to Kiedy się zakończy. Każda operacja potrwa pewien czas. Niektóre operacje trwają niezwykle długo, inne są niesamowicie szybkie.
Wysyłanie wierzchołka na GPU będzie tak szybko, że nawet nie wiem, jak to wyrazić. Wysyłanie tysięcy wierzchołków z procesora na GPU, każda pojedyncza klatka jest najprawdopodobniej bez problemu.
Czyszczenie ekranu może trwać milisekundę lub gorzej (należy pamiętać, że zwykle trzeba mieć około 16 milisekund czasu na narysowanie każdej klatki), w zależności od wielkości ekranu. Aby to wyczyścić, OpenGL musi narysować każdy pojedynczy piksel w kolorze, który chcesz oczyścić, czyli milion pikseli.
Poza tym możemy prawie tylko poprosić OpenGL o możliwości naszego adaptera graficznego (maksymalna rozdzielczość, maksymalne wygładzanie, maksymalna głębia kolorów, ...).
Ale możemy również wypełnić teksturę pikselami, z których każdy ma określony kolor. Każdy piksel zawiera zatem wartość, a tekstura jest gigantycznym "plikiem" wypełnionym danymi. Możemy załadować to na kartę graficzną (tworząc bufor tekstur), a następnie załadować moduł cieniujący, powiedzieć, że moduł cieniujący wykorzystuje naszą teksturę jako dane wejściowe i uruchamia wyjątkowo ciężkie obliczenia w naszym "pliku".
Możemy następnie "renderować" wynik naszego obliczenia (w postaci nowych kolorów) do nowej tekstury.
W ten sposób możesz sprawić, by GPU działało dla ciebie w inny sposób. Zakładam, że CUDA działa podobnie do tego aspektu, ale nigdy nie miałem okazji pracować z nim.
Naprawdę tylko nieznacznie poruszyliśmy cały temat. Programowanie grafiki 3D to piekielna bestia.
Źródło obrazu
Czy masz coś do dodania do wyjaśnienia? Dźwięk w komentarzach. Chcesz przeczytać więcej odpowiedzi od innych użytkowników Stack Exchange, którzy znają się na technologii? Sprawdź cały wątek dyskusji tutaj.