shader-ak

Gure ordenagailuko PUZaren bidez pantailan irudi bat bistaratzeko, pixelak goiko ezkerreko ertzetik hasi eta eskuinera eta beheti doaz. Kalkulu anitz egitea eskatzen duten 3D pantailaratzeekin gauza bera pasatuko da: jokoak, CAD programak… Lan handia suposatzen dio kalkulu guzti horiek egiteak PUZari. Grafikoen prozesu horiek modu eraginkorrago batean egiteko sortu ziren GPUak (Grafikoak Prozesatzeko Unitatea). Unitate honen bidez marraztutako grafiakoak hagitzez azkarrago kalkulatu eta bistaratzen dira.

GPUa ez da grafikoetarako bakarrik erabiltzen, funtzio matematiko berezi batzuk mikrotxipean bertan ebazten dira, softwaren bidez egin beharrean, baino post hau ez dut hori azaltzeko hasi.

Zergatik da GPUa horren azkarra?

Erran bezala, PUZ unitateak pixelak banaka pantailaratzen ditu, goiko ezkerretik beheitiko eskuineko ertzera, zutabez zutabe eta errenkadaz errenkada. GPUak berriz, pixel guztiak aldi berean margotzen ditu pantailan. Bideo labur honekin argi gelditzen dela erranen nuke:

Objektuen pantailaratze prozesua

GPUaren marrazte prozesuan hainbat atal daude. Atal horietako batzuk programagarriak dira eta programa horiei shader deitzen zaie. Programa horiek sortzeko C antzeko hainbat lengoaia daude, baino zabalduenetarikoa eta hemengo adibideetan jarriko dudana GLSL (openGL Shading Language) da. Marrazte prozesu horretan bi atal programagarri nagusi daude: Vertex shader eta Fragment shader. Gehiago ere badaude, baino horiek biek dira garrantzitsuenak.

Vertex shader

Bistaratu nahi den objektuko erpin bakoitzeko exekutatuko den programa da. Programa honen erabilera ohikoena 3 dimentsiotako grafikoak bistaratzeko prozesuan dago. 3D eszenak kameren bidez bistaratzen dira. Spoiler: Kamerak ez dira existitzen eta kalkulu matematikoekin simulatzen da kameraren ikuspuntua. Eszena hori kameratik ikusiko litzatekeen moduan erakusteko, kalkulu matematikoak shader honetan aplikatzen zaio erpin bakoitzari. Horretarako, kameraren posizioa eta orientazioa gordetzen dituen matrize eta objektuaren erpinen berezko posizioaren arteko biderketa batekin kalkulatzen da erpin bakoitza bistaratuko den kokapena.

adibidea

1
2
3
4
5
in vec3 erpinPosizioa;
uniform mat4 proiekzioMatrizea;
void main() {
gl_Position = vec4(erpinPosizioa, 1.0) * proiekzioMatrizea;
}

gl_Position GLSL lengoaiak duen aldagai berezi bat du, une horretan tratatzen ari den erpinaren posizioa definitzeko erabiltzen dena. erpinPosizioa eta proiekzioMatrizea parametro moduan pasatutako bi aldagai dira. Lehenengoa parametroan, tratatzen ari den objektuaren erpinaren berezko posizioa dago. Bigarrenean berriz, kameraren posizioa eta orientazioa adierazten dituen matrize bat. Bi horien biderketarekin lortuko da pantailako zein puntutan erakutsi behar den objektuaren erpin jakin hori.

Fragment shader

Fragment shader batek pantailak bistaratuko duen pixelaren kolorea itzuliko du. Hori da bere eginbeharra. Metodo honen azkartasunaren gakoa pixel guzti horiek aldi berean prozesatzen direla da. PUZak banan banan vs. GPUak denak aldi berean.

Pixelak guztiak aldi berean prozesatzeko modu honek ez digu uzten ondoko pixelaren irteera kolorea zein izanen den jakiten. Pixel bakoitza guztiz independentea da. Horrek zailago egiten du efektuak lortzea, baino erronka interesgarriagoa sortzen du aldi berean.

adibidea

1
2
3
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // r, g, b, a
}

Erpinen shader-ean erabilitako gl_Positionen antzeko aldagai berezi bat da gl_FragColor. Honekin, une honetan tratatzen ari den pixelaren kolorea definituko da, kasu honetan gorria. Hauen antzeko aldagai berezi gehiago daude, adibidez, uneko pixelak bistaratuko den leihoarekiko duen posizio erlatiboa ematen digun gl_FragCoord.

Hutsetik hasteko hagitz gomendagarria da thebookofshaders.com webgunea. Eta zerbait ikasi duzunean eta saltseatzen hasi edo inspiratzeko Shadertoy ere webgune interesgarria da.