Tietokoneen keskusyksikkö (CPU) ja grafiikkayksikkö (GPU) toimivat vuorovaikutuksessa jokaisen hetken kanssa, kun käytät tietokonetta, jotta saat terävän ja reagoivan visuaalisen käyttöliittymän. Lue lisää paremmin, miten he työskentelevät yhdessä.
Kuvaaja sskennel.
Tämän päivän kysymys- ja vastausistunto tulee meihin SuperUserin ansiosta. Tämä on Stack Exchange -jako, joka on Q & A-sivustojen yhteisöjoukkoyhtymä.
SuperUser-lukija Sathya esitti kysymyksen:
Täältä näet kuvakaappauksen pienestä C ++ -ohjelmasta nimeltä Triangle.exe, jossa on pyörivä kolmio, joka perustuu OpenGL API: iin.
Tosin hyvin yksinkertainen esimerkki, mutta mielestäni sitä voidaan soveltaa muihin graafisten korttien toimintoihin.
Olin vain utelias ja halusin tietää koko prosessin kaksoisnapsauttamalla Triangle.exe -ohjelmaa Windows XP: ssä, kunnes näen kolmion, joka pyörii näytössä. Mitä tapahtuu, miten vuorovaikutuksessa suoritetaan CPU (joka käsittelee ensin .exe) ja GPU: n (joka lopulta tuottaa kolmiota näytöllä)?
Luulen, että tämä pyörivä kolmio näytetään pääasiassa seuraavista laitteistoista / ohjelmista muun muassa:
Laitteisto
Ohjelmisto
Voiko kukaan selittää prosessi, ehkä jonkinlaisella vuokaavalla havainnollistamiseksi?
Sen ei pitäisi olla monimutkainen selitys, joka kattaa jokaisen askeleen (arvaus, joka ylittäisi soveltamisalaa), mutta selitys, jolla välittäjä IT-kaveri voi seurata.
Olen melko varma, että monet ihmiset, jotka jopa kutsuisivat itseään IT-ammattilaiset, eivät pystyneet kuvaamaan tätä prosessia oikein.
Vaikka useat yhteisön jäsenet vastasivat kysymykseen, Oliver Salzburg meni ylimääräiselle mailille ja vastasi siihen paitsi yksityiskohtaisella vastauksella, mutta erinomaisella mukana olevilla grafiikoilla.
Kuva JasonC, saatavilla taustakuvana tässä.
Hän kirjoittaa:
Päätin kirjoittaa hieman ohjelmoinnin näkökulmasta ja miten osat puhuvat toisilleen. Ehkä se tuo valoa tietyille alueille.
Mitä se tarvitsee edes siihen yksittäiseen kuvaan, joka lähetit kysymykseesi, piirretään näytölle?
Kolmio voidaan piirtää näytöllä monella tapaa. Yksinkertaisuuden vuoksi oletetaan, ettei vertex -puskuria käytetä. (A kärkipuskurion muistipaikka, jossa tallennat koordinaatit.) Oletetaan, että ohjelma yksinkertaisesti kertoi grafiikkaprosessin jokaisesta yksittäisestä kärkestä (vertex on vain koordinaatti avaruudessa) peräkkäin.
Mutta, ennen kuin voimme tehdä mitään, meidän on ensin ajettava rakennustelineitä. Katsotaan miksi myöhemmin:
// Tyhjennä näytön ja syvyyden puskurin glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Nollaa nykyinen mallinnusmatriisi glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Piirustus Kolmiot glBegin (GL_TRIANGLES); // punainen glColor3f (1.0f, 0.0f, 0.0f); // Top Of Triangle (edestä) glVertex3f (0.0f, 1.0f, 0.0f); // Vihreä glColor3f (0.0f, 1.0f, 0.0f); // vasemmalle kolmiosta (edestä) glVertex3f (-1.0f, -1.0f, 1.0f); // sininen glColor3f (0.0f, 0.0f, 1.0f); // Triangle Oikeus (Etuosa) glVertex3f (1.0f, -1.0f, 1.0f); // Valmis piirustus glEnd ();
Kun kirjoitat ohjelmaa, joka haluaa käyttää näytönohjainta, valitset yleensä jonkinlaisen käyttöliittymän kuljettajalle. Jotkut tunnetut liitännät kuljettajalle ovat:
Tässä esimerkissä pidämme kiinni OpenGL: stä. Nyt sinun käyttöliittymä antaa sinulle kaikki tarvittavat työkalut ohjelmasi tekemiseen puhua näytönohjain (tai kuljettaja, joka sitten neuvottelut kortille).
Tämä käyttöliittymä on varmasti varma Työkalut. Nämä työkalut muodostavat sovellusliittymän, jonka voit soittaa ohjelmasta.
Tämä sovellusliittymä on sellainen, jota voimme nähdä yllä olevassa esimerkissä. Katsotaanpa tarkemmin.
Ennen kuin voit todella tehdä mitään todellista piirrosta, sinun on tehtävä a perustaa. Sinun on määritettävä näkymäsi (alue, joka todella tehdään), perspektiivi ( kamera osaksi maailmaasi), mitä anti-aliasingia käytät (tasoitat kolmiota reunasta) ...
Mutta emme tarkastele mitään siitä. Me vain katsomme tavaroista, joita sinun täytyy tehdä jokainen kehys. Kuten:
Näytön tyhjentäminen
Grafiikkaputkijohto ei aio tyhjentää näyttöä jokaiselle kehykselle. Sinun täytyy kertoa se. Miksi? Tämän vuoksi:
Jos et poista näyttöä, voit yksinkertaisesti vetää pois se kaikki kehykset. Siksi kutsumme glClear
kanssaGL_COLOR_BUFFER_BIT
sarja. Toinen bitti (GL_DEPTH_BUFFER_BIT
) kertoo OpenGL: lle tyhjentää syvyyspuskuri. Tätä puskuria käytetään määrittämään, mitkä pikselit ovat muiden pikselien edessä (tai takana).
muutos
Kuvan lähde
Transformointi on osa, jossa otamme kaikki syöttökohdat (kolmiomme pisteet) ja käytämme ModelView-matriisiamme. Tämä on matriisi, joka selittää miten meidän malli- (vertikaalit) pyöritetään, skaalataan ja käännetään (siirretään).
Seuraavaksi sovellamme projektiomatriisiamme. Tämä siirtää kaikki koordinaatit, jotta ne kohtaavat kameramme oikein.
Nyt muutamme jälleen Viewport-matriisiamme. Teemme tämän mittakaavassa malli- monitorimme kokoon. Nyt meillä on joukko huippupisteitä, jotka ovat valmiita tekemään!
Palataan muutokseen hieman myöhemmin.
Piirustus
Piirrä kolmio, voimme yksinkertaisesti kertoa OpenGL: lle aloittaa uusi luettelo kolmioista soittamalla glBegin
kanssa GL_TRIANGLES
vakio.
Voit myös piirtää muita lomakkeita. Kuten kolmio-nauha tai kolmio-tuuletin. Nämä ovat ensisijaisesti optimointeja, koska ne edellyttävät vähemmän kommunikaatiota suorittimen ja GPU: n välillä, jotta saadaan sama määrä kolmioita.
Sen jälkeen voimme tarjota luettelon kolmesta huippupisteestä, joiden pitäisi muodostaa jokainen kolmio. Jokainen kolmio käyttää 3 koordinaattia (kuten 3D-tilassa). Lisäksi annan myös a väri- jokaiselle huippupisteelle, soittamallaglColor3f
ennen kutsumus glVertex3f
.
Kolmen pisteen (kolmiomaisen kolmion kulmat) välinen sävy lasketaan OpenGL: lläautomaattisesti. Se interpoloi värin monikulmion koko pinnan päälle.
Nyt, kun napsautat ikkunaa. Sovelluksen on vain kaapattava ikkunaviesti, joka ilmoittaa napsautuksesta. Sitten voit suorittaa mitä tahansa haluamaasi ohjelmaa.
Tämä saa a erä vaikeampi, kun haluat aloittaa vuorovaikutuksen 3D-kohtauksen kanssa.
Sinun on ensin tiedettävä, missä pikselissä käyttäjä napsautti ikkunaa. Sitten, otat teidän näkökulmahuomioon, voit laskea säteen suuntaan hiiren napsautuksesta pisteestä kohtaasi. Tämän jälkeen voit laskea mikä tahansa esine kohtaasi leikkaa tuon säteen kanssa. Nyt tiedät, onko käyttäjä napsauttanut objektia.
Joten, miten voit kiertää sitä?
Tiedän kahdenlaisia muutoksia, joita yleensä sovelletaan:
Ero on se luut vaikuttaa yksin kärkipisteet. Matriisit vaikuttavat aina kaikkiin vedettyihin pisteisiin samalla tavalla. Katsotaanpa esimerkkiä.
esimerkki
Aiemmin ladattiin meidän identiteettimatriisi ennen kuin piirimme kolmiomme. Identiteettimatriisi on yksi, joka yksinkertaisesti tarjoaa ei muutosta ollenkaan. Joten mitä minä vetän, vaikuttaa vain perspektiini. Joten kolmioa ei pyöritä ollenkaan.
Jos haluan kiertää sitä nyt, voisin joko tehdä itse matematiikan (suorittimella) ja soittaa glVertex3f
kanssamuut koordinaatit (jotka pyöritetään). Tai voisin antaa GPU: lle tehdä kaiken työn kutsumalla glRotatef
ennen piirustusta:
// Kierrä kolmiota Y-akselilla glRotatef (määrä, 0.0f, 1.0f, 0.0f);
määrä
on tietysti vain kiinteä arvo. Jos haluat elävöittää, sinun pitää seurata määrä
ja lisää sitä jokaisella kehyksellä.
Tässä yksinkertaisessa esimerkissä emme tarvitse huolehtia matriiseista. Me vain soitamme glRotatef
ja se hoitaa kaiken meidän puolestamme.
glRotate
tuottaa pyörimisenkulma
asteet vektorin x y z ympärillä. Nykyinen matriisi (seeglMatrixMode) kerrotaan pyörimismatriisilla nykyisen matriisin korvaavalla tuotteella, koska ifglMultMatrix kutsuttiin seuraavalla matriisilla argumenttinaan:x-1-c-zx-x-1-c-zx-x-1-c + 1-c-x-0-x-1-c-x-syy-1-c + x 2z 1 -c + c 0 0 0 0 1
No, kiitos siitä!
Mikä ilmeinen on, on paljon puhetta että OpenGL. Mutta se ei kerro meille mitä vain. Missä viestintä on?
Ainoa asia, jota OpenGL kertoo tässä esimerkissä, on kun se on tehty. Jokainen toiminta vie jonkin verran aikaa. Jotkut toiminnot ovat uskomattoman pitkät, toiset ovat uskomattoman nopeasti.
Sumteen lähettäminen GPU on niin nopea, en edes tiedä miten ilmaista sitä. Lähettämällä tuhansia huippupisteitä suorittimesta GPU: han, jokainen yksittäinen kehys, on todennäköisesti ongelmaton.
Näytön tyhjentäminen voi kestää jopa millisekuntia tai huonompi (muista, että sinulla on yleensä vain noin 16 millisekuntia aikaa piirtää kutakin kehystä) riippuen siitä, kuinka suuri näkymäsi on. Poistaaksesi sen, OpenGL: n on piirrettävä jokainen yksittäinen pikseli väriä, jonka haluat tyhjentää, joka voi olla miljoonia pikseleitä.
Muutoin voimme vain kysyä OpenGL: stä grafiikkasovittimemme ominaisuuksista (maksimaalinen tarkkuus, maksimaalinen aliaksennus, maksimaalinen värien syvyys ...).
Mutta voimme myös täyttää tekstuurin, jossa on pikseleitä, joilla kaikilla on tietty väri. Jokainen pikseli siis pitää arvossa ja tekstuuri on jättiläinen "tiedosto", joka on täynnä tietoja. Voimme ladata sen grafiikkakorttiin (luomalla tekstuuripuskuri), sitten ladata shaderin, kertoa, että shader käyttää tekstuuria panoksena ja suorittaa erittäin suuria laskelmia "tiedostossamme".
Sitten voimme laskea laskentamme tuloksen (uuden värin muodossa) uuteen tekstuuriin.
Näin voit tehdä GPU: n toimivan sinulle muillakin tavoilla. Oletan, että CUDA suorittaa samanlaisia kuin tämä näkökohta, mutta minulla ei koskaan ollut mahdollisuutta työskennellä sen kanssa.
Olemme todella koskettaneet vain koko aiheen. 3D-grafiikan ohjelmointi on helvetin peto.
Kuvanlähde
Onko jokin asia lisättävä selitykseen? Kuulkaa kommentit. Haluatko lukea lisää vastauksia muilta tech-tajuilta Stack Exchange-käyttäjiltä? Katso koko keskusteluketju täältä.