Hlavní navigace

OpenGL Imaging Subset (2)

9. 3. 2004
Doba čtení: 8 minut

Sdílet

V dnešní části seriálu o OpenGL Imaging Subsetu si řekneme, jakým způsobem mohou být změněny hodnoty pixelů během přenosu z a do framebufferu. Zaměříme se na operace prováděné jak v "základním" OpenGL, tak i v Imaging Subsetu.

Obsah

Změna hodnot během přenosu pixelů a fragmentů
Zpracování pixelů nesoucích informaci o barvě
Zpracování pixelů nesoucích index do barevné palety
Zpracování pixelů s informacemi o hloubce
Zpracování pixelů s informacemi o šabloně
Pokračování
Seznam funkcí zmíněných v této části
Zkomprimovaná verze článku

Změna hodnot během přenosu pixelů a fragmentů

Mezi framebufferem a operační pamětí počítače lze přenášet pixely, jejichž hodnoty mohou mít různý význam. Pokud je pixel zapisován či čten z barvového bufferu (color bufferu), má jeho hodnota význam barvy, pokud je zapisován či čten z paměti hloubky (depth bufferu), obsahuje hloubku fragmentu, a pokud se pracuje s pamětí šablony, obsahuje hodnotu zapisovanou nebo čtenou z paměti šablony (stencil bufferu).

Hodnoty přenášených pixelů se mohou v průběhu přenosu (transferu) změnit. Imaging subset je při inicializaci grafické knihovny OpenGL nastavený tak, že se i při povoleném zpracování pixelů (změně světlosti, kontrastu, mapování apod.) jejich hodnoty nijak nezmění. Způsob změny hodnot přenášených pixelů se řídí pomocí funkce:

void glPixelTransferi(
    GLenum  param,
    GLint   value
);

resp.

void glPixelTransferf(
    GLenum  param,
    GLfloat value
);

V argumentu param je zadána symbolická konstanta specifikující, který parametr ovlivňující konverzi hodnot pixelů budeme nastavovat, v argumentu value je potom zadána číselná hodnota tohoto parametru. Pokud je hodnota parametru value mimo povolené meze, generuje se chybová hodnota GL_INVALID_VALUE. Pokud je zadán nesprávný argumentparam, generuje se chybová hodnota GL_INVALID_ENUM. Tyto chybové hodnoty lze zjistit pomocí funkce glGetError(), kterou jsme si popsali v předchozí části tohoto seriálu.

V následující tabulce je uveden soupis všech parametrů, které je možné nastavit, i s jejich datovým typem, počáteční hodnotou a povoleným rozsahem hodnot:

Tabulka č. 549
Jméno parametru Typ
Počáteční hodnota
Rozsah hodnot
GL_MAP_COLOR GLboolean
GL_FALSE
GL_TRUE/GL_FALSE
GL_MAP_STENCIL GLboolean
GL_FALSE
GL_TRUE/GL_FALSE
GL_INDEX_SHIFT GLint
0
MIN_INT-MAX_INT
GL_INDEX_OFFSET GLint
0
MIN_INT-MAX_INT
GL_RED_SCALE GLfloat
1.0
celý rozsah GLfloat
GL_GREEN_SCALE GLfloat
1.0
celý rozsah GLfloat
GL_BLUE_SCALE GLfloat
1.0
celý rozsah GLfloat
GL_ALPHA_SCALE GLfloat
1.0
celý rozsah GLfloat
GL_DEPTH_SCALE GLfloat
1.0
celý rozsah GLfloat
GL_RED_BIAS GLfloat
0.0
celý rozsah GLfloat
GL_GREEN_BIAS GLfloat
0.0
celý rozsah GLfloat
GL_BLUE_BIAS GLfloat
0.0
celý rozsah GLfloat
GL_ALPHA_BIAS GLfloat
0.0
celý rozsah GLfloat
GL_DEPTH_BIAS GLfloat
0.0
celý rozsah GLfloat
GL_POST_CONVO­LUTION_RED_SCA­LE GLfloat
1.0
celý rozsah GLfloat
GL_POST_CONVO­LUTION_GREEN_SCA­LE GLfloat
1.0
celý rozsah GLfloat
GL_POST_CONVO­LUTION_BLUE_SCA­LE GLfloat
1.0
celý rozsah GLfloat
GL_POST_CONVO­LUTION_ALPHA_SCA­LE GLfloat
1.0
celý rozsah GLfloat
GL_POST_CONVO­LUTION_RED_BI­AS GLfloat
0.0
celý rozsah GLfloat
GL_POST_CONVO­LUTION_GREEN_BI­AS GLfloat
0.0
celý rozsah GLfloat
GL_POST_CONVO­LUTION_BLUE_BI­AS GLfloat
0.0
celý rozsah GLfloat
GL_POST_CONVO­LUTION_ALPHA_BI­AS GLfloat
0.0
celý rozsah GLfloat
GL_POST_COLOR_MAT­RIX_RED_SCALE GLfloat
1.0
celý rozsah GLfloat
GL_POST_COLOR_MAT­RIX_GREEN_SCA­LE GLfloat
1.0
celý rozsah GLfloat
GL_POST_COLOR_MAT­RIX_BLUE_SCALE GLfloat
1.0
celý rozsah GLfloat
GL_POST_COLOR_MAT­RIX_ALPHA_SCA­LE GLfloat
1.0
celý rozsah GLfloat
GL_POST_COLOR_MAT­RIX_RED_BIAS GLfloat
0.0
celý rozsah GLfloat
GL_POST_COLOR_MAT­RIX_GREEN_BIAS GLfloat
0.0
celý rozsah GLfloat
GL_POST_COLOR_MAT­RIX_BLUE_BIAS GLfloat
0.0
celý rozsah GLfloat
GL_POST_COLOR_MAT­RIX_ALPHA_BIAS GLfloat
0.0
celý rozsah GLfloat

Zpracování pixelů nesoucích informaci o barvě

Pixely, které nesou informaci o barvě v režimu true-color (formát RGB nebo RGBA), jsou během přenosu modifikovány podle následujícího schématu:

  1. Každá barvová složka (včetně alfa složky, kterou v tomto případě nerozlišujeme od pravých barvových složek) je nejprve vynásobena příslušnou hodnotou scale. Tato hodnota je nastavena pomocí funkce glPixelTransfe­ri() nebo glPixelTransfer­f() se jmény parametrůGL_RED_SCA­LE, GL_GREEN_SCALE, GL_BLUE_SCALE a GL_ALPHA_SCALE a hodnotami typu GLint resp. GLfloat. Pokud ponecháme původní nastavení OpenGL, jako při inicializaci, jsou všechny hodnoty scale nastaveny na jedničku, tj. barvové složky se vynásobením nezmění.
  2. K hodnotám barev, které vznikly výpočtem v předchozím bloku, jsou připočteny konstanty bias, které se taktéž nastavují pomocí funkce glPixelTransfer*(). V tomto případě jsou však použita jména parametrů GL_RED_BIAS, GL_GREEN_BIAS, GL_BLUE_BIAS a GL_ALPHA_BIAS s hodnotami typu GLfloat. Původní nastavení OpenGL je takové, že inicializační hodnoty bias jsou nastaveny na nulu, tj. barvy se přičtením těchto hodnot nijak nezmění.
  3. Po provedení předchozích dvou operací jsou hodnoty vypočtených barev oříznuty do rozsahu 0.0–1.0.
  4. Pokud je nastavena operace mapování hodnot pomocí tabulek LUT, tj. byla zavolána funkce glPixelTransfer(GL_MAP_­COLOR, GL_TRUE), je každá barvová hodnota vynásobena velikostí LUT tabulky a v této tabulce je vyhledán řádek s vypočteným indexem (vzhledem k tomu, že hodnota pixelu byla předem ořezána do rozsahu 0.0–1.0, je tato operace v pořádku a nikdy nemůže dojít k tomu, že by se index odkazoval mimo tabulku). Nová hodnota barvy pixelu je poté z vyhledávací tabulky nebo tabulek přečtena. Pokud je pro každou barvovou složku alokována tabulka s jinou velikostí, vypočtou se indexy pro každou barvu samostatně (samozřejmě, že korektně).
  5. Po mapování pomocí LUT je opět provedeno oříznutí hodnot barev do rozsahu 0.0–1.0. V případě, že imaging subset není podporován nebo je vypnut, zpracování v tomto bodu končí a vypočtené RGBA hodnoty se mohou zapsat do framebufferu.
  6. V případě, že je podporován imaging subset, je možné na výsledný obrázek aplikovat jednoduchý konvoluční filtr, který může být buď jednorozměrný, nebo dvourozměrný. Pokud jsou parametry konvolučního filtru zadány a filtrace je povolena, je v tomto bodu aplikován na pixely ukládané do framebufferu.
  7. Po provedení filtrace, kde na každou barvovou složku může být aplikován jiný konvoluční filtr, se provede opětovné vynásobení každé barvové složky hodnotou uloženou v konstantách GL_POST_CONVO­LUTION_RED_SCA­LE,GL_POST_CON­VOLUTION_GREEN_SCA­LE, GL_POST_CONVO­LUTION_BLUE_SCA­LE a GL_POST_CONVO­LUTION_ALPHA_SCA­LE. Inicializační hodnota těchto konstant je rovna jedné, tj. barvové složky se vynásobením nezmění.
  8. Následně je ke každé barvové složce přičtena jedna z konstant GL_POST_CONVO­LUTION_RED_BI­AS, GL_POST_CONVO­LUTION_GREEN_BI­AS, GL_POST_CONVO­LUTION_BLUE_BI­AS aGL_POST_CONVO­LUTION_ALPHA_BI­AS. Inicializační hodnota těchto konstant je rovna nule, opět se tedy nemění hodnoty zpracovávaných barvových složek.

Zpracování pixelů nesoucích index do barevné palety

Pixely, které nesou informaci o barvě v paletovém (index color) režimu, jsou během přenosu modifikovány poněkud odlišným způsobem než pixely, které obsahují true-color barvu:

  1. Hodnota pixelu (což je, jak již víme, číslo v pevné řádové čárce) je posunuta pomocí operace bitového posunu doleva o GL_INDEX_SHIFT bitů, nové bity z pravé strany jsou doplněny nulami. Pokud je pomocí funkce glPixelTransfer*() zadáno do parametru GL_INDEX_SHIFT záporné číslo, provádí se bitový posun doprava, nové bity se opět vyplňují nulami (jde tedy o unsigned hodnoty).
  2. K nové hodnotě pixelu je připočtena konstanta GL_INDEX_OFFSET, která je opět zadána pomocí funkce glPixelTransfer*().
  3. Pokud je barvový buffer nastaven do paletového režimu, je provedeno překódování barev pomocí vyhledávací tabulky – viz dále popsaná funkce glPixelMap(). Přitom je použita tabulka GL_PIXEL_MAP_I_TO­_I.
  4. Pokud jsou barvové buffery nastaveny do režimu pravých barev (RGBA, true color), jsou indexy do barevné palety zkonvertovány na pravé barvy. To se provede tak, že z vyhledávacích tabulek GL_PIXEL_MAP_I_TO­_R, GL_PIXEL_MAP_I_TO­_G, GL_PIXEL_MAP_I_TO­_B a GL_PIXEL_MAP_I_TO­_A jsou přečteny jednotlivé barvy na indexu odpovídajícím hodnotě pixelu. Všechny čtyři vyhledávací tabulky jsou opět specifikovány pomocí funkce glPixelMap*(). Velikost vyhledávacích tabulek může být u jednotlivých barevných položek různá – indexy se však vždy vypočtou tak, aby přesně spadaly do velikosti tabulky.

Zpracování pixelů s informacemi o hloubce

Pixely, které nesou informace o hloubce, tj. jsou zapisovány do paměti hloubky (depth buffer, Z-buffer), nebo jsou z této paměti naopak čteny, se zpracovávají následovně:

  1. Hodnota pixelu je nejprve vynásobena konstantou GL_DEPTH_SCALE. Tato konstanta je nastavena pomocí funkce glPixelTransfer*().
  2. Následně je k výsledku předchozího výpočtu přičtena hodnota GL_DEPTH_BIAS, která je rovněž nastavena pomocí funkce glPixelTransfer*().
  3. Vzhledem k tomu, že všechny hodnoty zapisované do paměti hloubky musejí být v rozsahu 0.0–1.0, je provedeno ořezání výsledku z předchozí operace právě na tento rozsah.

Zpracování pixelů s informacemi o šabloně

Pixely, které nesou hodnoty zapisované do paměti šablony (stencil bufferu), nebo jsou z této paměti čteny, jsou zpracovávány podle následujícího postupu:

UX DAy - tip 2

  1. Každá čtená či zapisovaná hodnota pixelu je posunuta o konstantuGL_IN­DEX_SHIFT. Tato operace je podobná operaci, která se provádí s pixely obsahujícími informace o indexu barvy. Kladná hodnota konstanty GL_INDEX_SHIFT značí posun doleva, záporná hodnota posun doprava.
  2. Hodnota získaná z předchozího bodu je přičtena ke konstantě GL_INDEX_OFFSET.
  3. Podobně jako u pixelů s indexovými barvami, i zde se může provést mapování podle nastavené vyhledávací tabulky – ovšem pouze v případě, že je mapování povoleno, viz GL_MAP_STENCIL. Velikost vyhledávací tabulky odpovídá hodnotě GL_PIXEL_MAP_S_TO­_S_SIZE.

Pokračování

V dalším pokračování tohoto seriálu si popíšeme vytvoření LUT tabulek používaných pro mapování pixelů.

Seznam funkcí zmíněných v této části

glPixelTransferi()
glPixelTransferf()
glPixelMap()
glGetError()
 

Zkomprimovaná verze článku

Zkomprimovaná verze tohoto článku je umístěna zde.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.