verteks šejdrTakéVS, vertex programPokročilý

Definice

Vertex shader je program běžící na GPU pro každý vstupní vrchol modelu, který vypočítá jeho polohu pro další fáze grafické pipeline. Obvykle převádí souřadnice z prostoru objektu přes kameru do projekce a předává interpolovatelná data, například barvu, normálu nebo UV souřadnice, fragment shaderu.

Kategorie: Grafické programováníAktualizováno

Proč vertex shader rozhoduje o poloze geometrie

Vertex shader je jedna z programovatelných fází grafické pipeline. Zpracuje každý vrchol zvlášť: roh trojúhelníku, bod čáry nebo bod v mřížce modelu. Hlavní výsledek není barva pixelu, ale poloha vrcholu v prostoru, ve kterém už GPU ví, co se má oříznout, promítnout a poslat do rasterizace. Bez správně vypočítané polohy se objekt zobrazí špatně, zmizí mimo kameru nebo se rozpadne na nesmyslné trojúhelníky.

Vertex shader patří do širší rodiny shaderů. Programátor v něm obvykle popíše transformaci modelu, kamery a projekce pomocí matic. GPU pak stejný program spustí paralelně nad velkým počtem vrcholů, což je důvod, proč se tato práce neprovádí po jednom na CPU.

Co vertex shader dostane a co musí vrátit

Vstupem bývají atributy vrcholu: pozice, normála, barva, váhy kostí, indexy kostí nebo UV souřadnice pro texturu. Další data přicházejí jako uniformy, například transformační matice, čas animace nebo parametry kamery. Vertex shader z těchto hodnot vypočítá výstupy pro navazující fáze.

  • Povinný výstup: pozice vrcholu v klipovacím prostoru, v GLSL typicky proměnná gl_Position.
  • Volitelné výstupy: hodnoty předávané dále, například normála, UV souřadnice nebo barva.
  • Omezení: jeden běh shaderu typicky nezná sousední vrcholy a nemá rozhodovat o finální barvě každého pixelu.

Souřadnicové prostory bez magie

Grafický objekt nezačíná ve finální poloze na obrazovce. Model má vlastní lokální souřadnice, scéna má světové souřadnice, kamera zavádí pohledový prostor a projekce převádí 3D scénu do tvaru vhodného pro obrazovku. Vertex shader je místo, kde se tyto převody často skládají do jedné matice, aby GPU provedlo výpočet rychle a předvídatelně.

Typický GLSL zápis může vypadat takto:

layout(location = 0) in vec3 position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main() {
    gl_Position = projection * view * model * vec4(position, 1.0);
}

Kde končí práce vertex shaderu

Rasterizace převezme transformované vrcholy a určí, které fragmenty, přibližně kandidáti na pixely, trojúhelník pokrývá. Hodnoty předané z vertex shaderu se mezi vrcholy interpolují. Když vertex shader pošle UV souřadnice, fragment shader dostane pro každý fragment mezihodnotu odpovídající místu uvnitř trojúhelníku. Vertex shader tedy nepřebarvuje celou plochu, ale připravuje geometrii a data, ze kterých další fáze kreslí viditelný výsledek.

Praktický dopad na výkon a vzhled

Složitý vertex shader zdražuje zpracování každého vrcholu, ale často je levnější než dělat stejný výpočet pro každý fragment. Deformace trávy, vlnění látky, skinning postavy nebo instancované vykreslení tisíců objektů jsou typické úlohy, kde se vertex shader vyplatí. Nevhodné je cpát do něj logiku, která závisí na detailech pixelu, například jemné osvětlení z textury nebo průhlednost podle obrazového vzorku.

Příklady z praxe

  1. Vlnění hladiny v reálném čase

    Herní voda je tvořená hustou mřížkou vrcholů. Vertex shader posune výšku každého vrcholu podle času a vodorovné pozice, takže se hladina vlní bez přepočítávání celé sítě na CPU. Fragment shader potom může jen dopočítat barvu a odlesky.

    uniform float time;
    layout(location = 0) in vec3 position;
    
    void main() {
        vec3 p = position;
        p.y += sin(p.x * 4.0 + time) * 0.15;
        gl_Position = projection * view * model * vec4(p, 1.0);
    }
  2. Tisíce stromů z jednoho modelu

    Scéna s lesem může používat jeden model stromu a tisíce instancí s různou polohou, měřítkem a natočením. Vertex shader použije pro každou instanci jinou transformační matici, takže GPU vykreslí mnoho stromů bez tisíců samostatných draw callů. Výsledkem je nižší režie na CPU.

    layout(location = 0) in vec3 position;
    layout(location = 3) in mat4 instanceMatrix;
    
    void main() {
        gl_Position = projection * view * instanceMatrix * vec4(position, 1.0);
    }

Časté omyly

MýtusVertex shader obarvuje pixely na obrazovce.
Ve skutečnostiVertex shader pracuje s vrcholy, ne s jednotlivými pixely. Barvu fragmentů typicky počítá fragment shader, i když vertex shader mu může poslat hodnoty, které se později interpolují.
MýtusČím víc výpočtů přesunu do vertex shaderu, tím rychlejší bude grafika.
Ve skutečnostiVertex shader pomáhá hlavně u výpočtů závislých na vrcholech. Příliš složitý vertex shader může být úzké hrdlo u detailních modelů a některé výpočty stejně patří do fragment shaderu nebo compute shaderu.

Časté dotazy

Které výpočty patří do vertex shaderu a které do fragment shaderu?
Vertex shader počítá polohu a doprovodná data pro vrcholy, zatímco fragment shader počítá hodnoty pro fragmenty vzniklé po rasterizaci. Vertex shader se spouští podle počtu vrcholů, fragment shader podle pokrytých částí obrazu. Jemné texturování, per-pixel osvětlení a průhlednost obvykle patří do fragment shaderu, protože závisejí na konkrétním místě uvnitř trojúhelníku.
Může vertex shader sám vytvořit nové vrcholy modelu?
Vertex shader může měnit polohu existujících vrcholů, ale v běžné pipeline sám nevytváří libovolné nové trojúhelníky. Geometrie, kterou má GPU kreslit, musí být dodaná jako vertex buffery, indexy nebo vytvořená jinou fází či technikou. Pro přidávání detailu se používají například tessellation shadery, mesh shadery, compute shadery nebo příprava sítě na CPU.
Kdy se vyplatí přesunout výpočet z CPU do vertex shaderu?
Vertex shader je vhodný pro výpočty, které se dají dělat nezávisle pro každý vrchol a opakují se u mnoha objektů nebo snímků. Typickým příkladem je skinning postavy, jednoduchá procedurální deformace, billboard orientovaný ke kameře nebo transformace instancí. Přesun na GPU dává smysl hlavně tehdy, když by CPU jen mechanicky upravovalo velké množství vrcholů.
Co znamená chyba, že vertex shader nezapisuje gl_Position?
Chyba kolem gl_Position obvykle znamená, že vertex shader nezapsal povinnou výstupní pozici vrcholu nebo použil neplatný typ hodnoty. V GLSL musí být gl_Position vektor vec4 v klipovacím prostoru. Bez této hodnoty navazující fáze neví, kde se má primitivum nacházet, takže program nelze správně slinkovat nebo vykreslit.

Zdroje

  1. Vertex Shader(otevře se v novém okně)Khronos Group
  2. WebGL API(otevře se v novém okně)MDN Web Docs
  3. WebGPU Shading Language(otevře se v novém okně)World Wide Web Consortium

Související pojmy

Potřebujete to vyřešit v praxi?

Poradíme, jak na to ve vašem projektu

Vysvětlit pojem je jedna věc, navrhnout kolem něj funkční řešení druhá. Ozvěte se a probereme, co dává smysl u vás.