Úvod do HLSL shaderov v game maker Studio
Určite už si niektorí z vás všimli, že okrem objektov, sprites, pozadia, scriptov apod. Je v GM Studio navyše nový typ resource - shader. Ale čo to vlastne shader je? Jedná sa o (väčšinou) krátky program, ktorý slúži na úpravu vecí kreslených na obrazovku. Používa sa na rôzne efekty.
Shadery sa píšu buď v jazyku GLSL alebo HLSL. V tomto seriáli sa zameriame hlavne na tie v HLSL, ku koncu si povieme aj niečo o GLSL. HLSL je skrátená verzia názvu High Level Shading Language
Na rozdiel od klasických programov, ktoré sa spúšťa v procesore, beží shadery na grafickej karte. Vďaka tomu sú veľmi rýchle.
Každý shader sa skladá z dvoch častí: vertex a fragment. Časť vertex pracuje s vrcholmi trojuholníkov, konci čiar a pod. Používa sa v 3D grafike napr. Na tvorbu svetiel, hmly atď. Oproti tomu fragmentovať časť pracuje s jednotlivými pixely. Tá môže tvoriť napr. Čiernobiele sfarbenie a veľa iných úprav farieb.
Ale rozprávanie už bolo dosť, ideme si to vyskúšať. V tomto a niekoľkých ďalších dieloch budeme meniť len fragmentovať časť shaderov a ako vertexové časť (nie, vynechať jej nemôžeme ) Budeme používať tzv. Pass throught shader. Ten nerobí nič a vyzerá takto:
struct a2v { float4 Position : POSITION0; float4 Color : COLOR0; float2 Texcoord : TEXCOORD0; }; struct v2p { float4 Position : POSITION0; float4 Color : COLOR0; float2 Texcoord : TEXCOORD0; }; void main(in a2v IN, out v2p OUT) { OUT.Color = IN.Color; OUT.Texcoord = IN.Texcoord; OUT.Position = mul(gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION], IN.Position); }
Pozn. nezabudnite si hore v editore prepnúť jazyk na HLSL 9.
Zatiaľ si ho jednoducho skopírujte a nemusíte si ho ďalej všímať. Teraz si ešte ukážeme pass throught pre fragmentovať časť:
struct input{ float4 Color : COLOR0; float2 Texcoord : TEXCOORD0; }; struct output{ float4 Color : COLOR0; }; void main(in input IN, out output OUT) { OUT.Color = tex2D(gm_BaseTexture, IN.Texcoord); }
S tým už budeme pracovať, takže si ho trochu vysvetlíme. Kód sa dosť podobá jazyku C.
- Pomocou slová struct definujeme niečo ako skupinu rôznych premenných
- void main (...) je tzv. funkcia. Do nej budeme písať kódy našich shaderov
- OUT.Color je výsledná farba pixelu
- tex2D (gm_BaseTexture, IN.Texcoord) nám získa aktuálny pixel z textúry (obrázku)
Na testovanie shaderov sa hodí mať niečo, na čom je budeme skúšať. Použijeme na to tento obrázok:
Vytvoríme si objekt s týmto obrázkom a pomenujeme si ho napr. ShaderTester. Do eventu Draw vložíme nasledujúci kód:
shader_set(shader0); // nastaví shader draw_self(); // nakreslí sám sebe shader_reset(); // vypne shader
Vytvorte si miestnosť s týmto objektom a čiernym pozadím. Po spustení by sa mal normálne nakresliť obrázok bez akýchkoľvek úprav.
Teraz už začneme s úpravami Napríklad prehodíme červenú a zelenú zložku. Pre jednoduchosť budem uvádzať iba vnútro funkcie main.
float4 col = tex2D(gm_BaseTexture, IN.Texcoord); OUT.Color = float4(col.g, col.r, col.b, col.a);
A teraz vysvetlenie:
float4 col
- takto sa v HLSL vytvárajú premennej. Col je jej názov. float4 je typ premennej, vyjadruje skupinu štyroch reálnych čísel (vektor). Do tohto typu premenných budeme ukladať farby, viac si o dátových typoch povieme v budúcom dielitex2D(gm_BaseTexture, IN.Texcoord)
- toto už poznáme, získa nám to daný pixel z obrázkufloat4(col.g, col.r, col.b, col.a)
- takto sa vytvára farba zo zložiek RGBA, zložky berieme z premennej col, len sme prehodili R a G.
O farbách si toho povieme viac. Už vieme, že sa skladajú zo zložiek RGBA (red green blue alpha, kde alpha je priehľadnosť). Pri práci s farbami sa často používajú celé čísla od 0 do 255, ale v Shader je to trochu iné. Tam sa používajú desatinné čísla od 0 do 1. (napr. 255 -> 1, 128 -> 0.5 a pod.) Toho sa dá využiť na získanie určitej časti farby.
Napríklad budeme mať farbu v premennej color, z ktorej chceme získať oranžovú časť. Robí sa to tak, že premennú vynásobíme požadovanou farbou. Oranžová je (255, 128, 0), čo v našom prípade znamená (1, 0.5, 0). Alpha zložku necháme na 1.
float4 col = color * float4(1, 0.5, 0, 1);
Skúsime si nakresliť fialovú zložku obrázka. Určite už vás napadá, ako bude kód vyzerať.
float4 col = color * float4(1, 0.5, 0, 1);
Môžete si skúsiť pár ďalších farieb, stačí len meniť hodnoty v zátvorke.
Podmienky
Podmienky budú posledná vec, na ktorú sa v tomto dieli zameriame. Určite sa vám nepáči to ružové pozadie okolo obrázka. Pokiaľ ale obrázok ukladáme ako napr. JPEG alebo BMP, je to spôsob, ako označiť priehľadná miesta. Pomocou podmienky môžeme zabezpečiť, aby sa tieto miesta nevykreslovala. To docielime tak, že je vykreslíme so 100% priehľadnosťou (alpha = 0). Podmienky sa píšu rovnako ako v GML (a množstvu ďalších jazykov):
if(podmínka){ příkaz pokud je podmínka splněna }else{ příkaz pokud podmínka není splněna }
Tak ideme na to. Tá ružová farba je vytvorená ako 100% červené, 0% zelené, 100% modrej a 100% alpha. Pre nás to je teda 1, 0, 1, 1. Pretože v HLSL nemožno jednoducho porovnať dve farby, musíme porovnať ich jednotlivé zložky. K tomu použijeme operátor &&.
float4 col = tex2D(gm_BaseTexture, IN.Texcoord); if((col.r == 1) && (col.g == 0) && (col.b == 1) && (col.a == 1)) OUT.Color = float4(0, 0, 0, 0); else OUT.Color = col;
Podmienka by sa dala zjednodušiť pomocou funkcie TRUNC, ktorá zahodí desatinnú časť čísla. Na mieste jedničky (plné zložky) zostane jednička az čohokoľvek menšieho sa stane 0. Že je v premennej nula zistíme v podmienke takto -! Prom, čokoľvek väčšieho nájdeme pomocou samotného názvu:
float4 col = tex2D(gm_BaseTexture, IN.Texcoord); float4 tcol = trunc(col); if(tcol.r && !tcol.g && tcol.b && tcol.a) OUT.Color = float4(0, 0, 0, 0); else OUT.Color = col;
Tým by som tento diel zakončil. Nabudúce sa pozrieme na premenné a ich typy. Ak máte akýkoľvek dotaz, pod článkom v komentároch je na ne miesta dosť.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 109x (900.09 kB)
Aplikácia je vrátane zdrojových kódov v jazyku GameMaker