Beginner's Guide to Graphics Shaders Coding
Leer om grafiese shaders te skryf, leer om die krag van die GPU te benut, met die duisende kerne wat almal parallel loop. Dit is 'n soort programmering wat 'n ander ingesteldheid vereis, maar die ontsluiting van die potensiaal is die moeite werd.
Feitlik elke moderne grafiese simulasie wat jou sien, word op een of ander manier aangedryf deur kode wat geskryf is vir die GPU, van die realistiese beligtingseffekte in die voorste AAA-speletjies tot 2D na-verwerkings-effekte en vloeibare simulasies.
'N toneel in Minecraft, voor en na die toepassing van a few shaders.
Die doel van hierdie gids
Shader-programmering kom soms uit as 'n raaiselagtige swart magie en word dikwels verkeerd verstaan. Daar is baie voorbeeldkodes daar buite wat jou wys hoe om ongelooflike effekte te skep, maar bied min of geen verduideliking. Hierdie gids poog om die gaping te oorbrug. Ek sal meer fokus op die basiese beginsels van die skryf en verstaan ​​van shader-kode, sodat jou maklik van die begin af kan koppel, kombineer of skryf!
Dit is 'n algemene riglyn, so wat jou hier leer, sal van toepassing wees op enigiets wat shaders kan hardloop.
So, Wat is 'n Shader?
'N Shader is eenvoudig 'n program wat in die grafiese pyplyn loop en die rekenaar vertel hoe om elke pixel te lewer. Hierdie programme word shaders genoem omdat hulle dikwels vir beheer gebruik word lighting and shading effekte, maar daar is geen rede dat hulle nie ander spesiale effekte kan hanteer nie.
Shaders word in 'n spesiale skadu taal geskryf. Moenie bekommerd wees nie, jou hoef nie uit te gaan en 'n hele nuwe taal te leer nie; Ons sal GLSL (OpenGL Shading Language) gebruik, wat 'n C-agtige taal is. (Daar is baie shading languages daar buite vir verskillende platforms, maar aangesien alles aangepas is om op GPU te hardloop, is alles baie soortgelyk)
Kom ons spring in!
Ons sal ShaderToy vir hierdie tutoriaal gebruik. Hiermee kan jou begin met die programmering van shaders direk in jou blaaier, sonder die moeite om iets op te stel! (Dit gebruik WebGL vir lewering, so jou sal 'n blaaier nodig hê wat dit kan ondersteun.) Creating an account is opsioneel, maar is nuttig om jou kode te stoor.
Nota: ShaderToy is in beta by die skryf van hierdie artikel. Sommige klein UI / sintaks besonderhede kan effens anders wees.
As jou op New Shader klik, moet jou so iets sien:
Jou koppelvlak kan effens anders lyk as jy nie ingeteken is nie.
Die klein swart pyl aan die onderkant is wat jy kliek om jou kode saam te stel.
Ek gaan verduidelik hoe shaders in een sin werk. Is jou gereed? Hier gaan ons!
Die enigste doel van die skadu is om vier getalle terug te gee: r, g, b, en a.
Dis alles wat dit ooit doen of kan. Die funksie wat jou voor jou sien, loop vir elke pixel op die skerm. Dit gee al vier kleurwaardes, en dit word die kleur van die pixel. Dit heet Pixel Shader (soms genoem Fragment Shader).
Met ons in gedagte, laat ons probeer om ons skerm 'n soliede rooi te maak. Die rgba (rooi, groen, blou en 'alfa', wat die deursigtigheid definieer) gaan van 0 tot 1, dus al wat ons moet doen is om terug te keer r, g, b, a = 1,0,0,1. ShaderToy verwag dat die finale pixel kleur gestoor word in FragColor.
Baie geluk! Dit is jou eerste werkskerm!
Uitdaging: Kan jou dit verander na 'n stewige grys kleur?
vec4 is net 'n datatipe, so ons kon ons kleur as 'n veranderlike verklaar, soos dit:
Dit is egter nie baie opwindend nie. Ons kan die kode op honderde duisende pixels parallel uitvoer en ons stel hulle almal in dieselfde kleur.
Kom ons probeer om 'n helling oor die skerm te maak. Wel, ons kan nie veel doen sonder om 'n paar dinge te weet oor die pixel wat ons affekteer nie, soos sy ligging op die skerm ...
Die pixel shader gee 'n paar variables vir jou om te gebruik. Die nuttigste een vir ons is fragCoord, wat die pixel se x en y (en z, as jy in 3D werk) koördinate. Kom ons probeer om al die pixels op die linker helfte van die skerm swart te draai, en almal wat in die regter helfte rooi is:
Nota: Vir enige vec4, kan jou toegang verkry tot die komponente via obj.x, obj.y, obj.z en obj.w of via obj.r, obj.g, obj.b, obj.a. Hulle is ekwivalent; Dit is net 'n maklike manier om hulle te noem om jou kode meer leesbaar te maak, sodat wanneer ander obj.r sien, verstaan ​​hulle dat obj 'n kleur voorstel.
Sien jou 'n probleem met die bostaande kode? Probeer om te klik go fullscreen knoppie regs onder in jou voorskou venster.
Die verhouding van die rooi skerm sal verskil afhangende van die grootte van die skerm. Om te verseker dat presies die helfte van die skerm rooi is, moet ons weet hoe groot ons skerm is. Skerm grootte is nie 'n ingeboude veranderlike soos pixel plek was, want dit is gewoonlik aan jou, die programmeerder wat die app gebou het, om dit te stel. In hierdie geval is dit die ShaderToy-ontwikkelaars wat die skermgrootte stel.
As iets nie 'n ingeboude veranderlike is nie, kan jou die inligting van die SVE (jou hoofprogram) na die GPU stuur (u skaduwee). ShaderToy hanteer dit vir ons. U kan sien dat al die veranderlikes in die skadu in die Shader Inputs-oortjie geslaag word. Veranderlikes wat op hierdie manier geslaag word van die SVE tot die GPU word uniform in GLSL genoem.
Kom ons pas ons kode hierbo om die middel van die skerm korrek te kry. Ons sal die shader-invoer moet gebruik iResolution:
As u die voorskou venster hierdie keer vergroot, moet die kleure nog steeds die helfte van die skerm perfek verdeel.
Van 'n verdeling tot 'n Gradiënt
Om dit in 'n helling te draai, moet redelik maklik wees. Ons kleurwaardes gaan van 0 tot 1, en ons koördinate gaan nou ook van 0 tot 1.
Uitdaging: Kan jou dit in 'n vertikale gradiënt verander? Wat van diagonaal? Wat van 'n gradiënt met meer as een kleur?
As jy so genoeg speel, kan jy sien dat die boonste linkerhoek koördinate (0,1), nie (0,0) het nie. Dit is belangrik om in gedagte te hou.
Om rond te speel met kleure is pret, maar as ons iets indrukwekkends wil doen, moet ons shader in staat wees om insette van 'n beeld te neem en dit te verander. Op hierdie manier kan ons 'n skaduwee maak wat ons hele spelskerm beïnvloed (soos 'n onderwater-vloeistof-effek of kleurkorreksie) of net sekere voorwerpe beïnvloed op sekere maniere gebaseer op die insette (soos 'n realistiese beligtingstelsel).
As ons op 'n normale platform program, moet ons ons beeld (of tekstuur) na die GPU stuur as 'n uniform, net soos u die skermresolusie sou stuur. ShaderToy sorg daarvoor vir ons. Daar is vier insetkanale aan die onderkant:
ShaderToy se vier insetkanale.
Klik op iChannel0 en kies enige tekstuur (prent) wat jy wil.
Sodra dit klaar is, het jou nou 'n beeld wat in jou skaduwee geslaag word. Daar is een probleem, Maar: daar is geen DrawImage () funksie. Onthou, die enigste ding wat die pixel shader ooit kan doen, is om die kleur van elke pixel te verander.
So as ons net die kleur kan herstel, hoe om tekstuur op die skerm te teken? Ons moet een of ander manier die huidige pixels van ons aktiewe shaders, na die ooreenstemmende pixels op die tekstuur, kaarteer:
Onthou, die boonste linker pixel op ons skerm is (0.1) terwyl die boonste linker pixel van die tekstuur (0,0) is, dus moet ons die y-as omkeer.
Ons kan dit met behulp van die texture2D-funksie (tekstuur, koördinaat), wat die tekstuur en die koördinaatpaar (x, y) as inset gebruik, en gee die tekstuurkleur na die koördinate as vec4.
Jou kan die koördinate ooreenstem met die skerm op enige manier wat jou wil. Jou kan die hele tekstuur op 'n kwart van die skerm teken (deur pixels te skuif, effektief te skaal) of net 'n gedeelte van die tekstuur te teken.
Vir ons doel, wil ons net die prent sien, so ons sal ooreenstem met die pixels 1: 1:
Met dit, ons het ons eerste foto!
Nou dat jou die data korrek uit die tekstuur trek, kan jou dit manipuleer soos jou wil! Jou kan dit rek en skaal, of met sy kleure speel.
Kom ons probeer hierdie wysiging met 'n gradiënt, soortgelyk aan wat ons hierbo doen:
Baie geluk, jou het pas jou eerste na-verwerkingseffek gemaak!
Uitdaging: Kan jou 'n skaduwee skryf wat die beeld na swart en wit verander?
Let daarop dat, hoewel dit 'n statiese beeld is, dit wat jou voor jou sien, in reële tyd gebeur. U kan dit self sien deur die statiese beeld met die video te vervang: klik weer op die iChannel0-inset en kies een van die video's.
Sommige bewegings bygevoeg
Tot dusver is al ons effekte staties. Ons kan baie meer interessante dinge doen deur die insette van ShaderToy te gebruik. iGlobalTime is 'n toenemende veranderlike; ons kan dit as 'n saad gebruik om 'n periodieke effek te skep. Kom ons probeer om met 'n bietjie kleur te speel:
Daar is sinus en cosinus funksies gebou in GLSL, sowel as baie ander nuttige funksies, soos om die vektor lengte of afstand tussen twee vektore te kry. Die kleure moet nie negatief wees nie, so ons maak seker dat ons 'n absolute waarde kry deur die abs-funksie te gebruik.
Uitdaging: Kan jou skaduwee maak wat foto's heen en weer van swart-wit na volle kleur verander?
Notas oor Debugging Shaders
Terwyl jy gewoond kan wees om deur jou kode te stap en die waardes van alles te druk om te sien wat gebeur, is dit nie regtig moontlik om shaders te skryf nie. Jou kan dalk spesiale ontfoutingshulpmiddels vir jou platform vind, maar oor die algemeen is jou beste verbintenis om die waardes wat jou toets, te stel aan iets waarmee jou grafika kan sien.
Dit is net die basiese beginsels om saam met shaders te werk, maar om gemaklik te wees met hierdie basiese beginsels sal jou toelaat om nog meer te doen. Browse through the effects on ShaderToy en kyk of jy sommige van hulle kan verstaan ​​of naboots!
Een ding wat ek nie in hierdie handleiding genoem het nie, is Vertex Shaders. Hulle word steeds in dieselfde taal geskryf, behalwe dat hulle op elke punt in plaas van elke pixel hardloop, en hulle herstel posisie en kleur. Vertex Shaders is gewoonlik verantwoordelik vir die uitbeelding van 3D-tonele op die skerm (iets wat in die meeste grafiese pype ingebou is). Pixel shaders is verantwoordelik vir baie van die kragtige effekte wat ons sien, daarom fokus hulle ons.
Laaste uitdaging: Kan jy 'n skaduwee skryf wat die groen skerm in die video op ShaderToy verwyder en 'n ander video as agtergrond vir die eerste een voeg?
Dit is alles vir hierdie gids! Ek waardeer jou terugvoer en jou vrae regtig. As daar iets spesifiek is wat jy meer wil leer, laat asseblief 'n opmerking. Toekomstige gidse kan onderwerpe insluit soos die basiese beginsels van 'n beligtingstelsel, of hoe om vloeistowwe te simuleer, of opstel van shaders vir spesifieke platforms.