Úvod do HLSL shaderů v GameMaker Studio
Určitě už si někteří z vás všimli, že kromě objektů, spritů, pozadí, scriptů apod. je v GM Studio navíc nový typ resource - shader. Ale co to vlastně shader je? Jedná se o (většinou) krátký program, který slouží k úpravě věcí kreslených na obrazovku. Používá se na různé efekty.
Shadery se píší buď v jazyce GLSL nebo HLSL. V tomhle seriálu se zaměříme hlavně na ty v HLSL, ke konci si řekneme i něco o GLSL. HLSL je zkrácená verze názvu High Level Shading Language
Na rozdíl od klasických programů, které se spouští v procesoru, běží shadery na grafické kartě. Díky tomu jsou velmi rychlé.
Každý shader se skládá ze dvou částí: vertex a fragment. Část vertex pracuje s vrcholy trojúhelníků, konci čar apod. Používá se ve 3D grafice např. na tvorbu světel, mlhy atd. Oproti tomu fragmentová část pracuje s jednotlivými pixely. Ta může tvořit např. černobílé zbarvení a spoustu jiných úprav barev.
Ale povídání už bylo dost, jdeme si to vyzkoušet. V tomto a několika dalších
dílech budeme měnit jen fragmentovou část shaderů a jako vertexovou část
(ne, vynechat jí nemůžeme
)
budeme používat tzv. pass throught shader. Ten nedělá nic a vypadá
takhle:
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. nezapomeňte si nahoře v editoru přepnout jazyk na HLSL 9.
Zatím si ho jednoduše zkopírujte a nemusíte si ho dále všímat. Teď si ještě ukážeme pass throught pro fragmentovou část:
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 pracovat, takže si ho trochu vysvětlíme. Kód se dost podobá jazyku C.
- Pomocí slova struct definujeme něco jako skupinu různých proměnných
- void main(...) je tzv. funkce. Do ní budeme psát kódy našich shaderů
- OUT.Color je výsledná barva pixelu
- tex2D(gm_BaseTexture, IN.Texcoord) nám získá aktuální pixel z textury (obrázku)
Na testování shaderů se hodí mít něco, na čem je budeme zkoušet. Použijeme k tomu tento obrázek:

Vytvoříme si objekt s tímto obrázkem a pojmenujeme si ho např. shaderTester. Do eventu Draw vložíme následující kód:
shader_set(shader0); // nastaví shader draw_self(); // nakreslí sám sebe shader_reset(); // vypne shader
Vytvořte si místnost s tímto objektem a černým pozadím. Po spuštění by se měl normálně nakreslit obrázek bez jakýchkoli úprav.

Teď už začneme s úpravami Například prohodíme červenou a zelenou složku. Pro jednoduchost
budu uvádět pouze vnitřek funkce main.
float4 col = tex2D(gm_BaseTexture, IN.Texcoord); OUT.Color = float4(col.g, col.r, col.b, col.a);

A teď vysvětlení:
float4 col
- takto se v HLSL vytvářejí proměnné. Col je její název. float4 je typ proměnné, vyjadřuje skupinu čtyř reálných čísel (vektor). Do tohoto typu proměnných budeme ukládat barvy, víc si o datových typech řekneme v příštím dílutex2D(gm_BaseTexture, IN.Texcoord)
- toto již známe, získá nám to daný pixel z obrázkufloat4(col.g, col.r, col.b, col.a)
- takhle se vytváří barva ze složek RGBA, složky bereme z proměnné col, jen jsme prohodili R a G.
O barvách si toho povíme více. Již víme, že se skládají ze složek rgba (red green blue alpha, kde alpha je průhlednost). Při práci s barvami se často používají celá čísla od 0 do 255, ale v shaderech je to trochu jiné. Tam se používají desetinná čísla od 0 do 1. (např. 255 -> 1, 128 -> 0.5 apod.) Toho se dá využít k získání určité části barvy.
Například budeme mít barvu v proměnné color, ze které chceme získat oranžovou část. Dělá se to tak, že proměnnou vynásobíme požadovanou barvou. Oranžová je (255, 128, 0), což v našem případě znamená (1, 0.5, 0). Alpha složku necháme na 1.
float4 col = color * float4(1, 0.5, 0, 1);
Zkusíme si nakreslit fialovou složku obrázku. Určitě už vás napadá, jak bude kód vypadat.
float4 col = color * float4(1, 0.5, 0, 1);

Můžete si zkusit pár dalších barev, stačí jen měnit hodnoty v závorce.
Podmínky
Podmínky budou poslední věc, na kterou se v tomto dílu zaměříme. Určitě se vám nelíbí to růžové pozadí okolo obrázku. Pokud ale obrázek ukládáme jako např. JPEG nebo BMP, je to způsob, jak označit průhledná místa. Pomocí podmínky můžeme zajistit, aby se tato místa nevykreslovala. Toho docílíme tak, že je vykreslíme se 100% průhledností (alpha = 0). Podmínky se píší stejně jako v GML (a spoustě dalších jazyků):
if(podmínka){ příkaz pokud je podmínka splněna }else{ příkaz pokud podmínka není splněna }
Tak jdeme na to. Ta růžová barva je vytvořená jako 100% červené, 0% zelené, 100% modré a 100% alpha. Pro nás to je tedy 1, 0, 1, 1. Protože v HLSL nelze jednoduše porovnat dvě barvy, musíme porovnat jejich jednotlivé slož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;

Podmínka by se dala zjednodušit pomocí funkce trunc, která zahodí desetinnou část čísla. Na místě jedničky (plné složky) zůstane jednička a z čehokoli menšího se stane 0. Že je v proměnné nula zjistíme v podmínce takto - !prom, cokoli většího najdeme pomocí 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 bych tenhle díl zakončil. Příště se podíváme na proměnné a jejich typy. Pokud máte jakýkoli dotaz, pod článkem v komentářích je na ně místa dost.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 109x (900.09 kB)
Aplikace je včetně zdrojových kódů v jazyce GameMaker