fi-notes/src/content/docs/szmgr/VPH07_gpu_rendering.md
2025-06-07 10:44:47 +02:00

16 KiB

title description
Renderování s využitím GPU (2023) TODO

Warning

Tato otázka zatím nebyla aktualizována. Nová varze obsahuje pár termínů navíc!

Note

Principy OpenGL, souřadnicové systémy (prostor světa, prostor kamery, prostor objektů), typy shaderů a jejich použití (vertex, fragment, compute, teselační). Technika stínových map. Principy odloženého stínování a jejich použití. Efekty prostoru obrazu (anti-alias, ambientní okluze).
PV227

  • OpenGL
    API pro (nejen) vykreslování grafiky na GPU.

    OpenGL® is the most widely adopted 2D and 3D graphics API in the industry, bringing thousands of applications to a wide variety of computer platforms. It is window-system and operating-system independent as well as network-transparent.

    — Khronos

    OpenGL je velký state machine, něco jako telefonní ústředna. Má bambilion funkcí, které mění globální stav, a jen několik funkcí (jako jsou glDraw*), které i něco doopravdy dělají. OpenGL je proto poměrně tolerantní k pořadí, v jakém jsou funkce volány.

    A large Bell System international switchboard in 1943

    width=500rem

  • OpenGL Shading Language (GLSL)
    Jazyk, ne nepodobný C, který se používá na psaní shaderů v OpenGL, WebGL a Vulkanu. Programy v něm (většinou) nejsou kompilované dopředu. Teprve za běhu programu jsou skrze OpenGL API ve zdrojové podobě předány GPU driveru, který je zkompiluje a spustí na GPU.

  • Primitives
    Způsob interpretace vertexových dat, která aplikace předává OpenGL.

    • Trojúhelníky (GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN),
    • čáry (GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP),
    • body (GL_POINTS),
    • patche (GL_PATCH) -- pro teselaci.

Souřadnicové systémy

Important

Tahle část otázky má značný překryv s otázkou Modelování a projekce.

Coordinate Systems 1

width=100%

  • Model space / local space / prostor objektu
    Každý vykreslený objekt má svůj lokální souřadnicový prostor daný editorem, ve kterém byl vytvořen, nastavením exportu a formátem, ve kterém byl vyexportován: 2

    Editor Handedness X Y Z
    Blender right-handed doprava dopředu nahoru
    3ds Max right-handed doprava dopředu nahoru
    Maya right-handed doprava nahoru dopředu
  • World space / prostor světa
    Globální prostor, ve kterém se objekty nachází. Měřítko je dáno aplikací.

    Z model space do world space převádíme souřadnice pomocí model matice (M). Ta nám umožňuje objekt nejen posunout ale i otočit a změnit jeho měřítko.

  • Camera space / view space / eye space / prostor kamery
    Prostor, který je viděn z pozice kamery.

    View matice (V) slouží k otočení, posunutí a případnému zvětšení nebo zmenšení prostoru světa tak, aby se objekty nacházely v prostoru před kamerou.

  • Clip space
    OpenGL očekává, že všechno, co bude vykresleno se nachází v jistém objemu -- clip space. Všechny souřadnice musíme do tohoto objemu převést a zároveň (pokud je to žádané) na ně aplikovat nějakou projekci (perspektivní, ortogonální, atd).

    Pro převod do clip space slouží projection matice (P). Ta nám umožňuje objekt nejen posunout ale i otočit a změnit jeho měřítko. 1

    Tento prostor stále používá 4-dimenzionální homogenní souřadnice.

  • Normalized Device Coordinates (NDC)
    NDC je jako clip space, ale po převodu z homogenních souřadnic do kartézských pomocí perspective divide (dělení w).

    V OpenGL je to kostka x \in (-1.0, 1.0), y \in (-1.0, 1.0), z \in (-1.0, 1.0).

  • Window / viewport space
    Má velikost danou rozlišením okna a glDepthRange. Ve výchozím nastavení je to x \in (0, width), y \in (0, height), z \in (0, 1).

    OpenGL převádí NDC do window space pomocí viewport transformace.

    Warning

    Počátek (origin) viewport space je vlevo dole a má ve výchozím nastavení má souřadnice (0, 0). 3

  • OpenGL handedness
    NDC v OpenGL je left-handed. Nicméně v OpenGL panuje konvence, že world space a camera space jsou right-handed (např. s glm). K přechodu dochází překlopením směru osy Z použitím projekční matice (P). 1 V OpenGL tedy platí:

    Space Handedness X Y Z
    Local záleží na modelu -- -- --
    World typicky right-handed doprava nahoru dozadu
    View typicky right-handed doprava nahoru dozadu (do kamery)
    Clip left-handed doprava nahoru dopředu
    NDC left-handed doprava nahoru dopředu
    Window left-handed doprava nahoru dopředu

    Tip

    Fun-fact: ve Vulkanu je NDC x \in (-1.0, 1.0), y \in (-1.0, 1.0), z \in (\textcolor{red}{0.0}, 1.0). A navíc je right-handed, takže souřadnice (-1.0, -1.0, 0.0) je vlevo nahoře, kdežto v OpenGL je vlevo dole. 4

Pipeline (typy shaderů)

Při zvolání glDraw* se používá OpenGL pipeline, která se skládá z několika fází: 5

Diagram of the Rendering Pipeline 5

vph07_pipeline

  • Vertex specification
    Fáze, kdy aplikace vytvoří popis vertexových dat, která posléze předá OpenGL. V téhle fázi se uplatňují Vertex Array Objecty (VAO) a Vertex Buffer Objecty (VBO).

  • Vertex shader (VS)
    Umožňuje programátorovi upravit data per vertex. Je spuštěn jednou, paralelně pro každý vertex.

  • Tesselation
    Volitelně umožňuje předaný patch rozdělit na více menších patchů (subdivision). Skládá se z:

    • Tesselation Control Shader (TSC): spuštěn jednou per patch a definuje míru, do jaké je patch rozdělen.
    • Tesselation Evaluation Shader (TES): je pak zodpovědný za interpolaci dat pro každý nový vertex.
  • Geometry shader (GS)
    Volitně umožňuje upravit / dogenerovat (teselovat) data per primitive. Je spušten jednou per primitive. Je mocnější než tesselation, ale tím pádem i méně efektivní.

  • Vertex post-processing
    OpenGL následně: 6

    1. sestaví primitives,

    2. ořeže je podle user clip space (nastavené programátorem v VS nebo GS pomocí gl_ClipDistance),

    3. provede perspective divide -- převede je do NDC:

      (x_{ndc}, y_{ndc}, z_{ndc}) = \left( \frac{x_{clip}}{w_{clip}}, \frac{y_{clip}}{w_{clip}}, \frac{z_{clip}}{w_{clip}} \right)
      
    4. převede je do window / viewport space:

      void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
      void glDepthRange(GLdouble nearVal, GLdouble farVal);
      void glDepthRangef(GLfloat nearVal, GLfloat farVal);
      
      \begin{pmatrix}
          x_{\textit{viewport}} \\
          y_{\textit{viewport}} \\
          z_{\textit{viewport}}
      \end{pmatrix}
      =
      \begin{pmatrix}
          \frac{\textit{width}}{2} \cdot x_{ndc} + x + \frac{\textit{width}}{2} \\
          \frac{\textit{height}}{2} \cdot y_{ndc} + y + \frac{\textit{height}}{2} \\
          \frac{\textit{farVal} - \textit{nearVal}}{2} \cdot z_{ndc} + \frac{\textit{farVal} + \textit{nearVal}}{2}
      \end{pmatrix}
      
    5. předá je do fragment shaderu.

  • Rasterization
    Proces, kdy si OpenGL musí uvědomit, které fragmenty (jeden nebo více pixelů, pokud je zapnutý multisampling) jsou pokryty primitivem.

  • Fragment shader (FS)
    Umožňuje programátorovi nastavit, co se stane s každým fragmentem -- nastavit mu barvu, hloubku, atd. Je spuštěn jednou, paralelně pro každý fragment. Data z VS jsou interpolována.

  • Per-sample operations
    Řada operací, která rozhoduje jak a jestli vůbec bude fragment vykreslen. Patří sem:

    • test "vlastnictví" -- OpenGL nebude vykreslovat před cizí okna,

    • scissor test -- zahodí fragmenty, které nejsou ve vytyčené oblasti,

    • stencil test -- zahodí fragmenty, které neprojdou testem na stencil buffer -- umožňuje např. implementovat Portal effect,

    • test hloubky -- zahodí fragmenty, které jsou zakryty jinými fragmenty,

      Tip

      Tenhle test se nemusí nutně stát až po FS. OpenGL se dá nastavit tak, aby provedlo early depth test před spuštěním FS.

    • color blending a bitwise operace.


  • Compute shader
    Shader, který není součástí vykreslovácí pipeline, neboť neslouží k vykreslování ale obecným výpočtům na GPU.

Shadow mapy

Important

Renderování stínů se věnuje také otázka Pokročilá počítačová grafika.

  1. Vytvoř shadow mapu -- vyrenderuj scénu z pohledu světla a ulož hloubku do Z-bufferu.
  2. Stínování -- vyrenderuj scénu jako obvykle, ale aplikuj shadow mapu
    1. Transformuj aktuální pixel do light-space souřadnic.
    2. Porovnej aktuální hloubku s hloubkou v shadow mapě.
    3. Změň osvětlení na základě porovnání.

The Shadow Mapping Depth Comparison 7

width=500rem

  • Jednoduché na implementaci, ale v základu má artefakty, které je potřeba vyřešit.

  • Vyžaduje alespoň dva průchody scénou.

  • Rozlišení shadow mapy limituje kvalitu stínů.

  • Shadow acne
    Problém shadow map, kdy objekty mylně vrhají stíny samy na sebe.

    Řeší se vykreslováním jen back-sided polygonů (glCullFace(GL_FRONT)), a nebo biasem -- srovnáním hloubky s malým biasem / posunem (obvykle epsilon).

    width=500rem

  • Peter Panning
    Když to s tím biasem přeženeme a objekty se začnou vznášet.

    No tak, trošku jsem si zapřeháněl.

    — Učitel

  • Aliasing
    Stíny mají "schodovité" hrany.

  • Warping
    Když shadow mapy nejsou samplovány uniformně, ale tak aby místa blíže ke kameře byla pokryta hustěji.

  • Cascaded Shadow Maps
    Pokrývají blízké oblasti scény více texely pomocí textur s různými rozlišeními, ve snaze bojovat proti aliasingu.

    width=500rem

  • Soft shadow maps -- Percentage-Closer Filtering (PCF)
    Rozmazává stíny uniformě fixním kernelem. 8

    width=500rem

  • Soft shadow maps -- Percentage-Closer Soft Shadows (PCSS)
    Počítá šíři penumbry pomocí velikosti světla, odhadu vzdálenosti blockeru (světlo-blokujícího objektu) od světla, a vzdálenosti mezi recieverem (objektem na který světlo dopadá) a blockerem. 8

    w_\text{penumbra} = \frac{p_z^s - z_\text{avg}}{z_\text{avg}} w_\text{light}
    

    width=500rem

Deferred shading / odložené stínování

Místo renderování přímo na obrazovku, vykreslíme scénu nejprve do textur (geometry pass), které označujeme jako G-buffer -- pozice, normály, barvy atd. Osvětlení je počítáno v odděleném průchodu (lighting pass) a vykresleno na obrazovku. 9

Tuto techniku použijeme např. když máme ve scéně fakt hodně světel.

vph07_deferred_shading

Important

Výhody:

  • osvětlení je počítáno jen jednou pro každý pixel,
  • můžeme mít více světel,
  • vyhodnocujeme méně různých kombinací materiálů a světel,
  • hodí se i na další post-process efekty.

Warning

Nevýhody:

  • vzdáváme se multisamplingu (resp. musíme nejprve použít edge detection, aby multisampling fungoval správně),
  • ztěžuje implementaci průhledných materiálů,
  • vyžaduje více paměti,
  • materiály nesmí být příliš komplikované kvůli omezeným možnostem paměti.

Screen space effects / efekty prostoru obrazu

Anti-aliasing

  • Aliasing
    Aliasing vzniká, když je sample rate nižší než Nyquist frequency. Projevuje se jako nová nízko-frekvenční informace, která v obrazu neexistuje. Při renderování se projevuje jako "schody" na hranách objektů.

    Aliasing 10

    width=500rem

  • Anti-aliasing
    Anti-aliasing jsou techniky, které zvyšují "samplovací frekvenci" renderování, a tak pomáhání eliminovat aliasing.

  • Super sample anti-aliasing (SSAA)
    Vyrenderujeme scénu v mnohem vyšším rozlišení a pak ji downscalujeme. Nevýhodou je, že počítáme mnohem více fragmentů.

  • Multisample anti-aliasing (MSAA)
    Pro každý pixel máme 2/4/8/... subsamply. Každý fragment počítáme jen jednou, ale podle toho, kolik subsamplů ho pokrývá, ho blendujeme s již existují barvou.

    MSAA 10

    width=500rem

Ambient occlusion

Ambient occlusion approximuje, jak moc je objekt vystaven ambientním světlu. Jinými slovy jak moc by měl být objekt v daném místě tmavý kvůli okolním objektům. Pokud používáme ray-tracing máme ambient occlusion "zadarmo", jelikož paprsky narazí na okolní objekty. Pokud nemáme ray tracing, můžeme použít nějakou fintu.

NVidia HBAO+

width=500rem

  • Screen-Space Ambient Occlusion (SSAO)
    Dívá se na okolí daného pixelu (v G-bufferu) a odhaduje tak jeho okluzi.

    SSAO 11

    width=500rem

Další zdroje