Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Ú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_Base­Texture, 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:

Obrázek ke stažení - GameMaker - Efekty

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.

nakreslený obrázek - GameMaker - Efekty

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);
prohození R a G - GameMaker - Efekty

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ílu
  • tex2D(gm_BaseTexture, IN.Texcoord) - toto již známe, získá nám to daný pixel z obrázku
  • float4(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);
Fialová složka obrázku - GameMaker - Efekty

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;
„umělá“ průhlednost - GameMaker - Efekty

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

 

Všechny články v sekci
GameMaker - Efekty
Článek pro vás napsal Zdeněk Pavlátka
Avatar
Uživatelské hodnocení:
4 hlasů
Autor se věnuje spoustě zajímavých věcí ze světa informatiky a grafiky
Aktivity