Tietokoneesi keskusyksikkö (CPU) ja grafiikkaprosessoriyksikkö (GPU) ovat vuorovaikutuksessa joka hetki, kun käytät tietokonetta toimittamaan sinulle terävän ja reagoivan visuaalisen käyttöliittymän. Lue lisää ymmärtääksesi paremmin, miten he työskentelevät yhdessä.
Kuva: sskennel .
Tämän päivän Kysymys- ja vastausistunto tulee meille SuperUser-lisenssillä - joka on Stack Exchangen alaryhmä.
Kysymys
SuperUser-lukija Sathya esitti kysymyksen:
Täältä näet kuvakaappauksen pienestä C ++ -ohjelmasta, jonka nimi on Triangle.exe ja pyörivä kolmio, joka perustuu OpenGL-sovellusliittymään.
Tosin hyvin yksinkertainen esimerkki, mutta mielestäni se soveltuu muihin grafiikkakorttitoimintoihin.
Olin vain utelias ja halusin tietää koko prosessin kaksoisnapsauttamalla Triangle.exe-tiedostoa Windows XP: ssä, kunnes näen kolmion pyörivän näytöllä. Mitä tapahtuu, miten CPU (joka ensin käsittelee .exe: n) ja GPU (joka lopulta tuottaa kolmion näytöllä) ovat vuorovaikutuksessa?
Luulen, että tämän pyörivän kolmion näyttämisessä on mukana ensisijaisesti seuraava laitteisto / ohjelmisto:
Laitteisto
- HDD
- Järjestelmän muisti (RAM)
- prosessori
- Videomuisti
- GPU
- LCD-näyttö
Ohjelmisto
- Käyttöjärjestelmä
- DirectX / OpenGL-sovellusliittymä
- Nvidia-ohjain
Voisiko kukaan selittää prosessin, ehkä jonkinlaisella vuokaavalla havainnollistamiseksi?
Sen ei pitäisi olla monimutkainen selitys, joka kattaa kaikki yksittäiset vaiheet (arvaus, joka menisi soveltamisalan ulkopuolelle), mutta selitys, jota väliteknologia voi seurata.
Olen melko varma, että monet ihmiset, jotka jopa kutsuvat itseään IT-ammattilaisiksi, eivät voineet kuvata tätä prosessia oikein.
Vastaus
Vaikka useat yhteisön jäsenet vastasivat kysymykseen, Oliver Salzburg meni ylimääräiselle mailille ja vastasi siihen paitsi yksityiskohtaisella vastauksella myös erinomaisilla mukana olevilla grafiikoilla.
Kuva JasonC, saatavana taustakuvana täältä .
Hän kirjoittaa:
Päätin kirjoittaa vähän ohjelmoinnista ja siitä, miten komponentit puhuvat keskenään. Ehkä se valaisee tiettyjä alueita.
Esitelmä
Mitä vaatii, että edes yksi kysymykseesi julkaisemasi kuva piirretään ruudulle?
Kolmion piirtäminen ruudulle on monia tapoja. Oletetaan yksinkertaisuuden vuoksi, ettei huippupuskureita käytetty. (A kärkipuskuri on muistialue, johon tallennat koordinaatit.) Oletetaan, että ohjelma kertoi yksinkertaisesti grafiikan käsittelyputkelle jokaisesta yksittäisestä pisteestä (kärki on vain koordinaatti avaruudessa) rivillä.
Mutta , ennen kuin voimme piirtää mitään, meidän on ensin ajettava rakennustelineitä. Katsotaan miksi myöhemmin:
// Tyhjennä näyttö ja syvyyspuskuri glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Nollaa nykyinen Modelview-matriisi glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Piirustus kolmioilla glBegin (GL_TRIANGLES); // Punainen glColor3f (1,0f, 0,0f, 0,0f); // Kolmion yläosa (edessä) glVertex3f (0,0f, 1,0f, 0,0f); // Vihreä glColor3f (0,0f, 1,0f, 0,0f); // Kolmion vasen puoli (edessä) glVertex3f (-1,0f, -1,0f, 1,0f); // Sininen glColor3f (0,0f, 0,0f, 1,0f); // Kolmion oikea (edessä) glVertex3f (1,0f, -1,0f, 1,0f); // Piirustus valmis glEnd ();
Joten mitä se teki?
Kun kirjoitat ohjelmaa, joka haluaa käyttää näytönohjainta, valitset yleensä jonkinlaisen käyttöliittymän ohjaimelle. Joitakin tunnettuja käyttöliittymiä kuljettajaan ovat:
- OpenGL
- Suora3D
- IMET
Tässä esimerkissä pidämme kiinni OpenGL: stä. Nyt sinun käyttöliittymä kuljettajaan antaa sinulle kaikki työkalut, joita tarvitset ohjelman tekemiseen puhua näytönohjaimelle (tai ohjaimelle, joka sitten neuvottelut kortille).
Tämä käyttöliittymä antaa sinulle varmasti työkalut . Nämä työkalut ovat ANTAA POTKUT johon voit soittaa ohjelmastasi.
Tätä sovellusliittymää käytämme yllä olevassa esimerkissä. Katsotaanpa tarkemmin.
Rakennustelineet
Ennen kuin voit todella tehdä todellisen piirustuksen, sinun on tehtävä perustaa . Sinun on määritettävä näkymä (alue, joka todella piirretään), näkökulma ( kamera maailmaasi), mitä anti-aliasia käytät (tasaamaan kolmion reunoja)…
Mutta emme tarkastele mitään. Kurkistamme vain tarvitsemasi asiat jokainen kehys . Kuten:
Näytön tyhjentäminen
Grafiikkaputki ei aio tyhjentää ruutua jokaiselle kehykselle. Sinun täytyy kertoa se. Miksi? Tämän vuoksi:
Jos et tyhjennä näyttöä, yksinkertaisesti
piirtää
se jokainen kehys. Siksi soitamme
glClear
kanssa
GL_COLOR_BUFFER_BIT
aseta. Toinen bitti (
GL_DEPTH_BUFFER_BIT
) käskee OpenGL: tä tyhjentämään
syvyys
puskuri. Tätä puskuria käytetään määrittämään, mitkä pikselit ovat muiden pikselien edessä (tai takana).
Muutos
Muunnos on osa, jossa otamme kaikki syöttökoordinaatit (kolmion pisteet) ja käytämme ModelView-matriisiamme. Tämä on matriisi, joka selittää kuinka meidän malli- (kärjet) käännetään, skaalataan ja käännetään (siirretään).
Seuraavaksi sovellamme projektiomatriisiamme. Tämä siirtää kaikki koordinaatit niin, että ne osoittavat kameraa oikein.
Nyt muutamme vielä kerran Viewport-matriisimme avulla. Teemme tämän skaalata malli- näytön koon mukaan. Nyt meillä on joukko pisteitä, jotka ovat valmiita hahmonnettavaksi!
Palataan muutokseen vähän myöhemmin.
Piirustus
Kolmion piirtämiseksi voimme yksinkertaisesti kertoa OpenGL: lle uuden aloittamisen
luettelo kolmioista
soittamalla
aloita
kanssa
GL_TRIANGLES
vakio.
Voit myös piirtää muita lomakkeita. Kuten
kolmion nauha
tai a
kolmion tuuletin
. Nämä ovat ensisijaisesti optimointeja, koska ne vaativat vähemmän tiedonsiirtoa suorittimen ja grafiikkasuorittimen välillä saman määrän kolmioiden piirtämiseksi.
Sen jälkeen voimme tarjota luettelon kolmesta pisteestä, joiden tulisi muodostaa kukin kolmio. Jokainen kolmio käyttää 3 koordinaattia (kuten olemme 3D-avaruudessa). Lisäksi annan myös a
väri-
kutakin kärkeä varten soittamalla
glColor3f
ennen
kutsumus
glVertex3f
.
Kolmen kärjen (kolmion 3 kulman) välinen sävy lasketaan OpenGL: n avulla automaattisesti . Se interpoloi värin monikulmion koko pinnalle.
Vuorovaikutus
Nyt kun napsautat ikkunaa. Sovelluksen on vain kaapattava ikkuna viesti joka merkitsee napsautusta. Sitten voit suorittaa minkä tahansa toiminnon haluamassasi ohjelmassa.
Tästä saa paljon vaikeampaa, kun haluat aloittaa vuorovaikutuksen 3D-kohtauksesi kanssa.
Ensin on tiedettävä selvästi, missä pikselissä käyttäjä napsautti ikkunaa. Sitten, kun otat näkökulmasta huomioon, voit laskea säteen suunnan hiiren napsautuksesta kohtaukseesi. Tämän jälkeen voit laskea, onko objektissasi kohtaus leikkaa tuon säteen kanssa . Nyt tiedät, napsauttiinko käyttäjä kohdetta.
Joten miten saat sen pyörimään?
Muutos
Olen tietoinen kahdesta muunnostyypistä, joita yleensä käytetään:
- Matriisipohjainen muunnos
- Luupohjainen transformaatio
Ero on siinä luut vaikuttaa yksin kärjet . Matriisit vaikuttavat aina kaikkiin piirrettyihin pisteisiin samalla tavalla. Katsotaanpa esimerkkiä.
Esimerkki
Aikaisemmin ladasimme identiteettimatriisi ennen kuin piirrämme kolmion. Identiteettimatriisi tarjoaa yksinkertaisesti ei muutosta ollenkaan. Joten mitä piirtään, vain perspektiivini vaikuttaa. Kolmiota ei siis käännetä lainkaan.
Jos haluan kiertää sitä nyt, voisin joko tehdä matematiikan itse (CPU: lla) ja yksinkertaisesti soittaa
glVertex3f
kanssa
muut
koordinaatit (jotka ovat pyörittyjä). Tai voisin antaa GPU: n tehdä kaiken työn soittamalla
glRotatef
ennen piirtämistä:
// Kierrä kolmiota Y-akselilla glRotatef (määrä, 0,0f, 1,0f, 0,0f);
määrä
on tietysti vain kiinteä arvo. Jos haluat
animoitu
, sinun on seurattava
määrä
ja lisää sitä jokaisessa kehyksessä.
Joten, odota, mitä tapahtui kaikille matriisipuheille aiemmin?
Tässä yksinkertaisessa esimerkissä meidän ei tarvitse välittää matriiseista. Soitamme vain
glRotatef
ja se huolehtii kaikesta siitä meille.
kiertäätuottaa pyörimisenkulmaastetta vektorin x y z ympärillä. Nykyinen matriisi (katso glMatrixMode ) kerrotaan kiertomatriisilla, jolloin tuote korvaa nykyisen matriisin ikään kuin glMultMatrix kutsuttiin argumenttina seuraava matriisi: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
No, kiitos siitä!
Johtopäätös
Mitä tulee ilmeiseksi, puhutaan paljon että OpenGL. Mutta se ei ole kerrottavaa meille mitä vain. Missä viestintä on?
Ainoa asia, jonka OpenGL kertoo meille tässä esimerkissä, on kun se on valmis . Jokainen toimenpide vie tietyn ajan. Jotkut toiminnot kestävät uskomattoman kauan, toiset ovat uskomattoman nopeita.
Kärkipisteen lähettäminen GPU: lle on niin nopea, en edes tiedä miten sitä ilmaista. Tuhansien pisteiden lähettäminen prosessorista GPU: han, jokainen kehys, ei todennäköisesti ole ongelma.
Näytön tyhjentäminen voi kestää millisekunnin tai huonompi (pidä mielessä, sinulla on yleensä vain noin 16 millisekuntia aikaa kunkin kuvan piirtämiseen), riippuen siitä, kuinka suuri näkymä on. Sen tyhjentämiseksi OpenGL: n on piirrettävä jokainen pikseli värillä, jolle haluat tyhjentää, se voi olla miljoonia pikseleitä.
Sen lisäksi voimme melkein kysyä vain OpenGL: ltä grafiikkasovittimemme ominaisuuksia (enimmäistarkkuus, enimmäisvastaus, suurin värisyvyys jne.).
Mutta voimme myös täyttää tekstuurin pikseleillä, joilla jokaisella on tietty väri. Jokaisella pikselillä on siis arvo ja rakenne on jättimäinen "tiedosto", joka on täynnä tietoja. Voimme ladata sen näytönohjaimelle (luomalla tekstuuripuskurin) ja ladata sitten a varjostin , käske varjostinta käyttämään tekstuuria tulona ja suorittamaan erittäin raskaita laskelmia tiedostollemme.
Sitten voimme "renderoida" laskennan tuloksen (uusien värien muodossa) uudeksi tekstuuriksi.
Näin voit saada GPU: n toimimaan sinulle muilla tavoilla. Oletan, että CUDA toimii samanlaisella tavalla kuin siinä, mutta minulla ei ole koskaan ollut mahdollisuutta työskennellä sen kanssa.
Koskimme oikeastaan vain vähän koko aihetta. 3D-grafiikan ohjelmointi on helvetin peto.
Onko sinulla jotain lisättävää selitykseen? Ääni pois kommenteista. Haluatko lukea lisää vastauksia muilta teknisesti taitavilta Stack Exchangen käyttäjiltä? Katso koko keskusteluketju täältä .