Nuotrauka pagal Sskennel.
Šiandieninė klausimų ir atsakymų sesija ateina pas mus "SuperUser" - "Stack Exchange", "Q &A" interneto svetainių grupių bendruomenės, padalinys.
Klausimas
SuperUser skaitytojas Sathya iškėlė klausimą:
Čia galite pamatyti mažos C + + programos "Triangle.exe" su rotacijos trikampiu ekraną, pagrįstą "OpenGL" API.
Man buvo tiesiog įdomu ir norėjau sužinoti visą procesą dukart spustelėdami "Triangle.exe", esantį "Windows XP", kol pamatysiu trikampį, rodytinį monitoriuje. Kas atsitiks, kaip sąveikauja CPU (kuris pirmiausia tvarko.exe) ir GPU (kuris pagaliau išveda trikampį ekrane)?
Manau, kad dalyvaujant rodomo trikampio rodymui pirmiausia yra ši aparatinė ir programinė įranga:
Techninė įranga
- HDD
- Sistemos atmintis (RAM)
- Procesorius
- Vaizdo atmintis
- GPU
- LCD ekranas
Programinė įranga
- Operacinė sistema
- DirectX / OpenGL API
- "Nvidia" tvarkyklė
Ar kas nors gali paaiškinti procesą, galbūt su tam tikra diagramos schema, skirta iliustracijai?
Tai neturėtų būti sudėtingas paaiškinimas, apimantis kiekvieną žingsnį (spėjama, kad jis viršytų taikymo sritį), tačiau paaiškinimas gali būti tarpinis IT žmogus.
Aš esu įsitikinęs, kad daugybė žmonių, kurie net vadintųsi save, IT specialistai negalėtų tinkamai apibūdinti šio proceso.
Atsakymas
Vaizdas, kurį pateikė Jasonas, čia galima atsisiųsti.
Jis rašo:
Aš nusprendžiau šiek tiek rašyti apie programavimo aspektą ir kaip komponentai kalba vienas kitam. Galbūt tam tikrose vietose bus šiek tiek šviesos.
Pristatymas
Ką daryti, kad netgi turėtumėte tą vieną vaizdą, kurį paskelbėte savo klausime, parodytą ekrane?
Yra daug būdų, kaip ekrane pavaizduoti trikampį. Paprastumo dėlei manysime, kad nebuvo naudojami viršūnių buferiai. (A viršūnių buferisyra atminties sritis, kurioje kaupiatės koordinatės.) Paimkime, kad programa paprasčiausiai supažindino grafikos apdorojimo vamzdyną apie kiekvieną viršūnę (viršūnė yra tik koordinatė erdvėje) iš eilės.
Bet, kol mes galime padaryti ką nors, mes pirmiausia turime paleisti kai kuriuos pastolius. Pamatysime kodėl vėliau:
// Clear The Screen And The Depth Buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset The Current Modelview Matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Drawing Using Triangles glBegin(GL_TRIANGLES); // Red glColor3f(1.0f,0.0f,0.0f); // Top Of Triangle (Front) glVertex3f( 0.0f, 1.0f, 0.0f); // Green 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); // Done Drawing glEnd();
Taigi, kas tai padarė?
Kai rašote programą, kuri nori naudoti grafikos plokštę, paprastai su tvarkykle pasirodys kokia nors sąsaja. Kai kurios žinomos sąsajos su vairuotoju:
- OpenGL
- Direct3D
- CUDA
Šiame pavyzdyje mes laikomės "OpenGL". Dabar tavo sąsaja su vairuotoju yra tai, kas suteikia jums visus įrankius, reikalingus jūsų programai atlikti kalbėti į grafikos plokštę (arba tvarkyklę, kuri tada derybos į kortelę).
Ši sąsaja privalo suteikti jums tam tikrą įrankiai. Šios priemonės yra API, kurį galite paskambinti iš programos, formos.
Šis API yra tai, ką mes matome naudojantis aukščiau pateiktame pavyzdyje. Paimkime arčiau.
Pastoliai
Kad galėtumėte iš tikrųjų atlikti bet kokį faktinį piešimą, turėsite atlikti a sąranka. Jūs turite apibrėžti savo peržiūros langą (teritoriją, kuri iš tikrųjų bus pateiktas), jūsų perspektyvą ( fotoaparatas į savo pasaulį), kokį anti-aliasingą jūs naudosite (norėdami išlyginti trikampio kraštus) …
Bet mes to nežiūrėsime. Mes tiesiog pažvelkime į dalykus, kuriuos turėsime padaryti kiekvienas rėmelis. Kaip:
Išvalyti ekraną
Grafinis dujotiekis nesiruošia išvalyti kiekvieno kadro ekrano. Turėsite tai pasakyti. Kodėl? Štai kodėl:
Jei neišvalysite ekrano, paprasčiausiai pritraukti tai kiekvienas rėmas. Štai kodėl mes vadiname
glClear
su
GL_COLOR_BUFFER_BIT
nustatyti. Kitas bitas (
GL_DEPTH_BUFFER_BIT
) sako "OpenGL" išvalyti gylisbuferis. Šis buferis naudojamas norint nustatyti, kurie taškai yra priešais (arba už juos) kitus pikselius.
Transformacija
Transformacija - tai dalis, kurioje imamės visos įvesties koordinatės (mūsų trikampio viršūnės) ir pritaikome ModelView matricą. Tai matrica paaiškina kaip mes modelis (viršūnės) yra pasuktos, mastelio ir verčiamos (perkeltos).
Toliau mes pritaikome mūsų projektavimo matricą. Tai perkelia visas koordinates, kad jie teisingai susidurtų su mūsų fotoaparatu.
Dabar mes dar kartą transformuojame su "Viewport" matrica. Mes tai darome, kad masto mūsų modelis iki monitoriaus dydžio. Dabar turime viršūnių rinkinį, kuris yra pasirengęs pateikti!
Vėliau grįšime prie transformacijos.
Brėžinys
Norėdami piešti trikampį, galime tiesiog pasakyti "OpenGL" pradėti naują trikampių sąrašas skambindami
glBegin
su
GL_TRIANGLES
pastovi Taip pat yra kitų formų, kurias galite piešti. Kaip trikampio juosta ar trikampio ventiliatorius.Tai pirmiausia optimizavimas, nes jie reikalauja mažiau bendravimo tarp procesoriaus ir GPU, kad sukauptų tokį patį trikampių kiekį.
Po to mes galime pateikti 3 viršūnių rinkinių, kurie turėtų sudaryti kiekvieną trikampį, sąrašą. Kiekvienas trikampis naudoja 3 koordinates (kaip mes esame 3D erdvėje). Be to, aš taip pat pateikiu a spalva už kiekvieną viršūnę, skambindami
glColor3f
anksčiau skambinti
glVertex3f
Tarp 3 viršūnių (3 kampai trikampio) atspalvis apskaičiuojamas OpenGL automatiškai. Jis interpoliuoti spalvą visame daugiakampio veidui.
Sąveika
Dabar, kai spustelėsite langą. Paraiška turi tik užfiksuoti lango pranešimą, kuris rodo spragtelėjimą. Tada galite paleisti bet kokius veiksmus savo programoje, kurią norite.
Tai pasireiškia daug sunkiau, kai norite pradėti bendrauti su 3D scenos.
Pirmiausia turite aiškiai žinoti, kokiu pikseliu naudotojas spustelėjo langą. Tada, pasiimk savo perspektyvaAtsižvelgiant į tai, jūs galite apskaičiuoti spindulių kryptį nuo pelės paspaudimo taško į savo sceną. Tada galite apskaičiuoti, ar jūsų objekte yra koks nors objektas kerta su ta ray. Dabar žinote, ar vartotojas spustelėjo objektą.
Taigi, kaip jūs jį sukite?
Transformacija
Aš žinau apie dviejų tipų transformacijas, kurios paprastai taikomos:
- Matrica pagrįsta transformacija
- Kaulų pagrindu transformacija
Skirtumas toks kaulai paveikti vieną viršūnės. Matricos visada įtakoja visus sukurtus viršus taip pat. Pažvelkime į pavyzdį.
Pavyzdys
Anksčiau mes pakrovome mūsų tapatybės matrica prieš piešdami mūsų trikampį. Identiška matrica yra ta, kuri tiesiog teikia jokios transformacijos iš viso. Taigi, ką darau, mano požiūris įtakoja tik. Taigi trikampis nebus apskritai pasukamas.
Jei aš noriu jį pasukti dabar, aš galėčiau arba pats atlikti matematiką (CPU) ir tiesiog skambinti
glVertex3f
sukita koordinatės (rotacijos). Arba galėčiau leisti GPU atlikti visą darbą, skambindamas
glRotatef
prieš piešiant:
// Rotate The Triangle On The Y axis glRotatef(amount,0.0f,1.0f,0.0f);
amount
yra, žinoma, tik fiksuota vertė. Jeigu nori gyvinti, turėsite stebėti
amount
ir padidinkite kiekvieną kadrą.
Taigi, palaukite, kas atsitiko su visais matricos pokalbiais anksčiau?
Šiame paprastame pavyzdyje mes neturime rūpintis matricomis. Mes tiesiog skambinu
glRotatef
ir jis rūpinasi visomis, kas už mus.
glRotate
sukuria rotaciją
angle
laipsniai aplink vektorių x y z. Dabartinė matrica (seeglMatrixMode) padauginama iš rotacijos matricos su produktu, pakeičiančiu dabartinę matricą, nes, kaip argumentas, ifglMultMatrix buvo pavadintas tokia matrica:
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 ç ¼ z ¹ 1 - c + x sz 2 ¹ 1 - c + c 0 0 0 0 1
Na, ačiū už tai!
Išvada
Tai, kas tampa akivaizdu, yra daug pokalbių į OpenGL. Bet tai ne pasakoja mus nieko. Kur yra ryšys?
Vienintelis dalykas, kurį OpenGL šiame pavyzdyje mums sako, - tai kai tai bus padaryta. Kiekviena operacija užtruks tam tikrą laiką. Kai kurios operacijos vykdomos neįtikėtinai ilgai, kitos yra neįtikėtinai greita.
Viršelio siuntimas į GPU bus taip greitai, aš net nežinau kaip tai išreikšti. Siunčiant tūkstančius viršūnių iš CPU į GPU, kiekvienas rėmelis greičiausiai nėra problema.
Išvalyti ekraną gali užtrukti milisekundę ar dar blogiau (atminkite, kad dažniausiai tik 16 milisekundžių laiko, kad parengtumėte kiekvieną rėmelį), priklausomai nuo to, kiek yra jūsų peržiūros taškas. Norėdami jį išvalyti, "OpenGL" turi atkreipti kiekvieną tašką, kurį norite išvalyti, kad būtų milijonai pikselių.
Išskyrus tai, mes galime tik garsiai paklausti "OpenGL" apie mūsų grafikos adapterio galimybes (maksimali raiška, maksimalus slopinimas, maksimalus spalvų gylis …).
Tačiau mes taip pat galime užpildyti tekstūrą su pikseliais, kurių kiekviena turi tam tikrą spalvą. Taigi kiekvienas pikselis turi vertę, o tekstūra yra milžiniškas "failas", užpildytas duomenimis. Galime jį įkelti į grafinę plokštę (sukurdami tekstūros buferį), tada įkelkite šaderį, pasakykite, kad šešėlis naudoja tekstūrą kaip įvesties elementą ir paleiskite keletą itin sunkių skaičiavimų mūsų "failo".
Tada mes galime "išversti" mūsų skaičiavimų rezultatą (naujų spalvų pavidalu) į naują tekstūrą.
Štai kaip jūs galite padaryti GPU darbą jums kitais būdais. Manau, kad CUDA atlieka panašų į šį aspektą, tačiau niekada neturėjau galimybės su ja dirbti.
Mes tik šiek tiek palietėme visą temą. 3D grafikos programavimas yra žvėries pragaras.
Ar turite ką nors įtraukti į paaiškinimą? Garsas išjungtas komentaruose. Norite skaityti daugiau atsakymų iš kitų "Tech-savvy Stack Exchange" vartotojų? Patikrinkite visą diskusijų temą čia.