Slutet på fixeringsrörledningar (och hur man går vidare)

Fasta rörledningar har inte mer verksamhet på våra grafikkort. Här är vad du behöver veta om dem - och hur man gör omkopplaren ifrån dem, om du fortfarande inte har gjort det ännu.

I början: Graden av grafikhårdvara

En gång i tiden, när spelutveckling (eller kodning av allt som har att göra med realtidsgrafik, verkligen) begränsades till att skriva till en relativt liten matris av färgintensiteter ( rambuffert) och skickar den till hårdvara, kan du göra allt du vill ha med det. Du kan rita till bilden en, tio eller hundra gånger. Du kan gå över rambufferten igen för att göra lite snyggt FX. Kort sagt, vad som helst som din processor kunde göra, kan du göra det till bilden som skickas till monitorn. Detta gjorde det möjligt för dig att göra några riktigt bra och kreativa saker, men människor brukade aldrig (eller sällan) använt det i den månen. Men varför?

Svaret: eftersom det var långsamt. En bild på 640 × 480 px (en gemensam upplösning vid den tiden) innehåller 307 200 pixlar. Och processorerna var så mycket långsammare då att du inte kunde göra mycket på den korta tiden som gavs dig att rita den ramen. När allt kommer omkring, om du vill fortsätta teckna på 30FPS, har du bara cirka 30mars för att uppdatera din spellogik och göra det till skärmen, och det måste inkludera omkostnaderna för kommunikationen med hårdvaran. Det var inte mycket.

Sedan kom de coola GPUerna med reningsrörledningar. Du, utvecklaren, skulle ta hand om att uppdatera spellogiken och skicka dina texturer och trianglar till GPU, och det skulle göra det tunga lyftandet och numret som knackade på dem. Det var fixeringsrörledningar med fast funktion (FFP): vilket innebär att du inte kunde konfigurera funktioner de utförde. Du kan berätta för dem "torka mörkgrå" eller "gör inte belysningen för mig!" och du kan konfigurera mycket av det andra parametrar, men funktioner själva förblev. 

Hårdvaran var trådbunden och smal specialiserad så att den utförde vissa standardoperationer på dina data. Och eftersom det var anslutet så var det så mycket snabbare än att göra dem på din processor. Men en nackdel var att du betalade mycket för den hastigheten: du betalade i flexibilitet. Men om du någonsin velat skriva någonting komplexa, var CPU helt enkelt inte tillräckligt snabb, och det var det enda valet att skicka in dina hörnpunkter till GPU..

Detta är ungefär hur fasta rörledningen fungerade. Bilden är inte avsedd som en korrekt representation, men för att ge dig en aning om hur allting utfördes.

Kraven på bättre realism

Grafvärlden förändrade sig fortfarande snabbt. Precis som alla kreativa och begåvade personer älskar spelutvecklare utmaningar och en av de Utmaningar för dem var (och kommer att förbli!), under lång tid, för att göra någonsin bättre och realistiska bilder. 

Rörledningen med fast funktion gav några fina funktioner, såsom flera blandningsmetoder, Gearaud-skuggning, dimmaffekter, stencilbuffertar (för skuggvolymer) och så, så utvecklarna använde vad de kunde. Snart var det några riktigt imponerande effekter på gång, allt på grund av verkliga fenomen som simulerades med hjälp av några billiga tricks (bra, billigt enligt dagens standarder). 

Det gick allt bra, men det var fortfarande begränsat av hur många funktioner den fasta rörledningen kunde göra. Den verkliga världen har trots allt så många olika material, och för att simulera dem var den enda variation som de fick göra att ändra vissa blandningsmetoder, lägga till några fler texturer eller justera ljusreflektionens färger.

Då hände det: de första programmerbara GPU: erna kom med. De kom inte överallt, och de var tvungna att komma fram en dag, men det skapade fortfarande spänning. Dessa GPU hade vad som kallades a programmerbar reningsrörledning: Du kan nu skriva program som heter shaders, i ett begränsat sammansättningsspråk, och få dem att utföras för varje vertex eller fragment, på videokortet. Detta var ett stort steg framåt, och det blev bara bättre. 

Snart ökade sammansättningsspråken i komplexitet och uttrycksfullhet, och språk på hög nivå för GPU-programmering framkom, till exempel HLSL, GLSL och senare Cg. Idag har vi geometriska shaders som även kan strömma ut nya vertikaler eller shaders som dynamiskt styr tessellation och tessellerade trianglar. Inuti dem kan vi prova en väldigt mycket texturer, dynamiskt gräva och göra alla slags galna matte på ingångsvärdena.

När du ger utvecklare dessa fördelar, går de vilda snart skrev de shaders för alla sorters saker: parallax kartläggning, anpassade belysningsmodeller, brytning, du heter det. Senare uppstod även helt anpassade belysningssystem, såsom uppskjuten skuggning och ljusförhand, och du kan se komplexa efterbehandlingseffekter som skärmutrymme, omgivande ocklusion och horisontell, omgivande ocklusion. Vissa var till och med "missbrukande" shaders att göra repetitiva, matte-tunga uppgifter, som statistisk bearbetning eller bryta sträng hash. (Detta var innan generell användning av datorer på GPU: er fick ett vanligt stöd.) 

Kort sagt, datorgrafik exploderade med introduktionen av shaders och med god anledning: förmågan att programmera vad som exakt hände med vertices, fragment, texturer och så vidare och att göra det snabb, gav nästan oändliga möjligheter.

En förenklad representation av den programmerbara rörledningen. Observera hur de specifika transformations-, skuggnings- eller textureringsstadierna ersattes av specialiserade shaders. (Tessellation utelämnas för tydlighet.)

Den fullständiga omkopplaren

Snart var fasta rörledningar föråldrade, åtminstone för spelutvecklare. Varför bry sig med sådana muromgärdade trädgårdar när du kan programmera exakt vad som händer med dina data? De användes mycket längre i vissa applikationer där realism inte var ett problem, till exempel för CAD. Men i stort sett blev de ignorerade. 

OpenGL ES 2.0, släppt 2007, avlägsnade eller avlägsnade sin fasta funktionsrörledning till förmån för en programmerbar. OpenGL 3.2, tillbaka 2009, tog slutligen bort alla begrepp av vertex med fast funktion och fragmentbehandling (det är dock fortfarande tillgängligt för äldre användning via en kompatibilitetsprofil). Det är uppenbart att det idag inte är så litet att arbeta med den begränsade rörledningen när du har kraftfulla GPU: er som kan göra fantastiska saker till ditt förfogande.

Eftersom de här API: erna tvingar dig att använda shaders (och det här inkluderar DirectX, som även om det inte är explicit att ta bort funktionaliteten, innehåller verktyg som hjälper mig att migrera från det gamla tillvägagångssättet och har praktiskt taget ingen ny dokumentation om FFP), de är svåra att få rätt för en nybörjare. Om du bara startar som en 3D-programmering, är det mycket lättare att bara berätta för API: erna din matriser, ljusparametrar och whatnot och gör det gör allt för dig. 

Men i det långa loppet kommer det att gynna dig mycket mer om du lär dig att skriva program som precis beskriver processen. Du förstår ingående vad som händer under huven, förstår några väldigt viktiga begrepp som FFP inte kräver dig, och du kan enkelt anpassa dina material för att göra något komplicerat, den fasta funktionen kan aldrig göra för dig (och det är användbart för debugging också!).

Jag har nämnt OpenGL ES, och låt mig bygga upp det mer detaljerat. Eftersom spel på mobil blir mer och mer populärt är det meningsfullt att skapa virtuella världar som ständigt ökar i komplexitet. De flesta av de fasta samtalen togs bort i ES 2.0 (vilket naturligtvis betyder att de är frånvarande från följande versioner också). Detta betyder i huvudsak att du behöver använda shaders för att kunna använda någon av funktionerna efter ES 1.1. 

ES 2.0 stöds av iPhones sedan 3GS, iPads sedan den första utgåvan och iPod Touch-enheter i generation 3 och högre. Qualcomm Snapdragon, ett chip som används ofta i Android-telefonproduktion, stöder också OpenGL ES 2.0. Det är väldigt bred stöd, för ES 2.0 är inte exakt "nytt": det är över 7 år nu. För att få ut mesta möjliga av dessa arkitekturer, du måste släppa fast rörledningen med fast funktion

Jag antar att de flesta av er har gjort så länge sedan, men det är inte så svårt för mig att föreställa mig några 2D-grafikmotorer eller äldre spel som fortfarande använder fast funktion (eftersom det inte finns något behov av mer). Det här är bra, men att använda det för nya projekt, eller träningsprogrammerare i dem, verkar som ett slöseri med tid. Detta förstärks av det faktum att många tutorials du kan hitta på Internet är grovt föråldrade och kommer att lära dig hur du använder FFP från början - och innan du ens inser vad som händer, kommer du att vara djup där.

Min första borste med 3D-grafik var en gammal DirectX 7-handledning skrivet i Visual Basic. Vid den tidpunkten var det vanligt att använda rörledningen med fast funktion, eftersom maskinvaran inte var tillräckligt avancerad för att uppnå samma funktionalitet med shaders i samma takt. Men idag ser vi grafik-API: er som börjar släppa eller drastiskt deprecierat stöd för det, och det blir verkligen bara en artefakt från det förflutna. Det är en bra och användbar artefakt som gör oss nostalgiska, men vi borde hålla sig borta från den. Det är gammalt och används inte längre.

Dessa söta fresnelreflektioner och refraktioner, genererade av en demo från OGRE (Open Source Graphics Rendering Engine), kunde aldrig ha gjorts om du klibbade sig på de sätt som gamla gamla DirectX 8 eller OpenGL 1.1-handledning rådde.

Slutsats

Om du spelar in i allvarlig spelutveckling är det en relik av förgångna dagar att hålla fast vid rörledningen. Om du tänker på 3D-grafik, är mitt råd (och råd från många, många utvecklare där ute) att helt enkelt undvika det. 

Om du ser överlämnande av belysningspositioner till grafik API (inte som en skuggparameter) eller API-funktionssamtal som glFogv, springa som vinden och titta inte tillbaka. Det finns en modig ny värld av programmerbara GPUer där ute, och det har funnits länge. Allting ökar förmodligen bara din tid.

Även om du bara är in i 2D-grafik, är det fortfarande en klok idé att inte lita på FFP längre. (Självklart är det så länge du är okej med att inte stödja någon gammal hårdvara.) Shaders kan ge dig några bra, blixtsnabba effekter. Bildavskärning, skärpning, varpnät, vektorframställning och storskalig partikel- eller fysiksimulering kan alla göras på GPU, och de kan alla gynna både 2D och 3D-spel. 

Så, igen, mitt råd, även om du inte explicit ska lära dig om 3D-spelutveckling, är att lära dig att skriva shaders. De är roliga att arbeta med, och jag garanterar att du ska spendera många roliga timmar som perfektar en cool shader-effekt: en dynamisk butty-skybox, bilfärg eller parallell-delad skuggmappning, eller vad ditt hjärta önskar. Det har åtminstone hänt mig: när du är van att arbeta med den fasta rörledningen på grund av en begränsning (som jag var tvungen att återvända till för att få acceptabel prestanda på min 5200FX), är programmeringen av GPU: n en blast och massor av roligt.

Jag hoppas att jag har förklarat dem för vilka det var oklart hur 3D-grafik brukade fungera för länge sedan och hur det fungerar nu, och jag hoppas jag har övertygat de få av er som var på väg att följa NeHe eller Swiftless tutorials att göra annars och gå och titta på något mer modernt. Som alltid kan jag ha gjort några misstag, så gärna uttrycka dem i kommentarerna. Tills nästa gång!