Obsah
1. Pohled pod kapotu JVM – práce s texturami v knihovně SDLJava
2. Nastavení parametrů textur v OpenGL
3. Rozšířená podpora formátů textur
4. Třída TextureFactory a objekt typu Texture
5. Demonstrační příklad SDLTest20 – texturování a objekt typu Texture
6. Demonstrační příklad SDLTest21 – opakování textury
7. Demonstrační příklad SDLTest22 – volba filtru použitého při zvětšování a zmenšování textury
8. Repositář se zdrojovými kódy všech čtyř dnešních demonstračních příkladů
1. Pohled pod kapotu JVM – práce s texturami v knihovně SDLJava
V dnešní části tohoto seriálu si ukážeme, jak je možné s využitím knihovny SDLJava a s ní propojené knihovny OpenGL používat texturování. Texturováním (resp. poněkud přesněji řečeno nanášením textur) je označen princip obarvení povrchu zobrazovacích těles různými obrazci. Důležité přitom je, že se nijak nemění geometrické vlastnosti těles, pouze se jiným způsobem zobrazuje jejich povrch. Obrazce, které se na povrch těles nanášejí, se nazývají textury (textures). Tyto textury jsou většinou představovány plošnými obrázky (dvoudimenzionální textury), některé grafické systémy však podporují i vykreslování jednorozměrných a dokonce trojrozměrných (objemových) textur.
Obrazce pro textury se mohou vytvářet několika způsoby. Buď je možné použít klasické rastrové obrázky (vzniklé například namalováním, vyfocením nebo naskenováním) nebo se textura může vytvářet pomocí různých algoritmů založených většinou na procedurálních a fraktálních technikách – tímto způsobem vznikají takzvané procedurální textury. Procedurální textury lze použít buď pro výpočet rastrových obrázků před vlastním vykreslováním (po výpočtu obrázku se tato textura chová jako každý jiný rastrový obrázek se všemi výhodami i nevýhodami) nebo se může výpočet textur provádět v reálném čase až při vykreslování, přičemž se parametry výpočtu textury nastaví podle aktuální velikosti a orientace plošky, na kterou se textura nanáší. Tuto druhou možnost však OpenGL přímo nepodporuje, výpočet procedurálních textur je tedy nutné provádět „ručně“, popř. lze použít shadery, tj. programy vykonávané přímo na GPU.
V dalším textu se budeme téměř výhradně zabývat texturami reprezentovanými rastrovými obrázky, nezávisle na tom, jakým způsobem vznikly. I když řeč bude převážně o dvoudimenzionálních texturách (tedy bitmapách a pixmapách), většina zde popisovaných vlastností se vztahuje i na jednorozměrné a trojrozměrné textury. Podobně jako je bitmapa či pixmapa složená ze základních rastrových elementů (pixelů), tak je textura složena z texelů. Pixel a texel mají stejné vlastnosti a podobný či dokonce ekvivalentní způsob uložení v paměti. V dalším textu však budeme oba pojmy navzájem oddělovat, tj. pixel je element vykreslovaný na obrazovce, kdežto texel je rastrový element (většinou) dvourozměrné textury. Texturování potom spočívá v nanášení texelů na vykreslovaný povrch.
Použití rastrových textur s sebou přináší samozřejmě své výhody i nevýhody. Jak jsme si již řekli, používá se technika texturování jako určitá náhrada při zobrazování složitých povrchů těles (zeď, omítka, dřevo, kámen), kdy se tento obecně nehomogenní povrch nahradí ploškou s nanesenou texturou. Záleží na vhodné volbě textury, velikosti objektu a nasvícení celé scény, zda tato náhrada bude dostatečná, či zda uživatel uvidí vizuální chyby ve scéně. Další předností texturování je, že pokud u textur použijeme průhlednost (nazývanou také alfa kanál), je možné vizuálně změnit geometrii předmětů, protože se předmět může na některých místech jevit jako děravý. Poznamenejme, že při použití průhlednosti je nutné programově setřídit průhledné nebo poloprůhledné plošky, jelikož by v tomto případě Z-buffer (paměť hloubky) nepracoval korektně – i průhledné texely by se „vykreslily“ a poškodily tak informaci o hloubce fragmentu uloženou v Z-bufferu.
2. Nastavení parametrů textur v OpenGL
V OpenGL lze také zvolit různé filtrace textur, režimy mapování textur na plošky, multitexturování a další grafické efekty, které si dále probereme. Musíme si však uvědomit, že pokud použijeme některý grafický efekt, který není grafickým akcelerátorem podporován, dojde k výpočtům pomocí hlavního procesoru počítače, což značně zpomaluje celý systém. Proto je nejprve vhodné zjistit, které efekty jsou na grafickém akcelerátoru podporovány a případně dát uživateli naší aplikace na výběr mezi kvalitou a rychlostí zobrazení (s těmito omezeními se dnes už prakticky nesetkáme).
Parametry textury (tj. například způsob, jakým je textura mapována na povrch vykreslovaného tělesa) lze nastavit voláním metody:
org.gljava.opengl.GL: void glTexParameterf( long target, long pname, float param );
nebo metody:
org.gljava.opengl.GL: void glTexParameteri( long target, long pname, int param );
Alternativně lze také zavolat metody, které jako svůj poslední parametr akceptují místo skalární hodnoty pole hodnot, které je však v případě SDLJava reprezentováno bufferem:
org.gljava.opengl.GL: void glTexParameterfv( long target, long pname, java.nio.FloatBuffer params );
void glTexParameteriv( long target, long pname, java.nio.IntBuffer params );
První parametr (target) může podle zvolené dimenze textury nabývat hodnot GL.GL_TEXTURE_1D (jednodimenzionální texura, tj. barevný přechod) nebo GL.GL_TEXTURE_2D (nejběžnější, rastrová textura). Hodnoty parametrů dalších dvou parametrů pname a value jsou uvedeny v následujícím seznamu:
- Parametr GL.GL_TEXTURE_WRAP_S:
tímto parametrem specifikujeme, zda se má při překročení rozsahu texturovací souřadnice ve směru osy s provést opakování motivu na textuře (value=GL.GL_REPEAT) nebo protažení první či poslední hodnoty (value=GL.GL_CLAMP). Opakování motivu na textuře je vhodné použít v případech, že zobrazujeme různé na sebe navazující motivy, například cihlové zdi, podlahy apod. Protažením textury lze v některých případech zamezit vizuálním artefaktům, které by se mohly objevit při napojování textur. Překročení rozsahu není tedy v žádném případě chybou, vyvoláme ho například příkazem GL.glTexCoord2f(2.0, 0.5). - Parametr GL.GL_TEXTURE_WRAP_T:
tento parametr má podobný význam jako parametr předchozí s tím rozdílem, že se místo na souřadnici ve směru osy s vztahuje na souřadnici ve směru osy t. U 1D textur nemá hodnota tohoto parametru vliv na zobrazení textury, použitelný je pouze u 2D textur. Opakování resp. protažení textury lze pro souřadnice ve všech směrech nastavovat nezávisle. - Parametr GL.GL_TEXTURE_MIN_FILTER:
tímto parametrem je možné zvolit filtr použitý při zmenšování textury, tj. tehdy, jestliže na plochu jednoho vykreslovaného pixelu musíme použít barvy několika sousedních texelů. Nejjednodušší a nejrychlejší filtr se volí hodnotou GL.GL_NEAREST. U tohoto filtru se barva vykreslovaného pixelu vypočte z barvy texelu, jehož souřadnice nejpřesněji odpovídají zadaným souřadnicím do textury. Poněkud sofistikovanější filtr se zadává hodnotou GL.GL_LINEAR, kdy se barva vykreslovaného pixelu spočítá pomocí bilineární interpolace z barev sousedních texelů. Další čtyři filtry (GL.GL_NEAREST_MIPMAP_NEAREST, GL.GL_NEAREST_MIPMAP_LINEAR, GL.GL_LINEAR_MIPMAP_NEAREST a GL.GL_LINEAR_MIPMAP_LINEAR) využívají takzvané mipmapy, jejichž význam si vysvětlíme příště. - Parametr GL.GL_TEXTURE_MAX_FILTER:
tímto parametrem se volí filtr použitý při zvětšování textury, tj. v případě, že vykreslovaný pixel obsahuje pouze malou plochu texelu. Možné hodnoty jsou GL.GL_NEAREST (použije se nejbližší texel) nebo GL.GL_LINEAR (použije se lineární interpolace mezi barvami sousedních texelů). - Parametr GL.GL_TEXTURE_BORDER_COLOR:
tímto parametrem lze zvolit barvu rámečku okolo textury (pokud je rámeček použit, tj. pokud má nenulovou šířku). V případě zadávání barvy je nutné použít příkazy GL.glTexParameteriv() resp. GL.glTexParameterfv(), protože barva se zadává jako vektor (pole, buffer) čtyř složek R, G, B a A. Implicitní barva rámečku je (0, 0, 0, 0), tedy černá.
3. Rozšířená podpora formátů textur
Kromě základních formátů textur je možné používat v OpenGL verze 1.2 a vyšších i další rozšířené formáty. Jaká výhoda plyne z použití takových formátů? Především jde o to, že použitím některých formátů s malou nebo dostatečnou bitovou hloubkou můžeme ušetřit paměť alokovanou pro textury. Druhou výhodou je možnost použít textury načtené z různých externích souborů, které mají mnohdy exotický formát. V následující tabulce budou ukázány rozšířené formáty textur spolu se základním formátem a typem dat pro každou barvovou složku:
Rozšířený formát | Základní formát | Počet bitů R | Počet bitů G | Počet bitů B | Počet bitů A | Luminance (úroveň bílé) | Intenzita (úroveň bílé=alpha) |
---|---|---|---|---|---|---|---|
GL_ALPHA4 | GL_ALPHA | 4 | |||||
GL_ALPHA8 | GL_ALPHA | 8 | |||||
GL_ALPHA12 | GL_ALPHA | 12 | |||||
GL_ALPHA16 | GL_ALPHA | 16 | |||||
GL_LUMINANCE4 | GL_LUMINANCE | 4 | |||||
GL_LUMINANCE8 | GL_LUMINANCE | 8 | |||||
GL_LUMINANCE12 | GL_LUMINANCE | 12 | |||||
GL_LUMINANCE16 | GL_LUMINANCE | 16 | |||||
GL_LUMINANCE4_ALPHA4 | GL_LUMINANCE_ALPHA | 4 | 4 | ||||
GL_LUMINANCE6_ALPHA2 | GL_LUMINANCE_ALPHA | 2 | 6 | ||||
GL_LUMINANCE8_ALPHA8 | GL_LUMINANCE_ALPHA | 8 | 8 | ||||
GL_LUMINANCE12_ALPHA4 | GL_LUMINANCE_ALPHA | 4 | 12 | ||||
GL_LUMINANCE12_ALPHA12 | GL_LUMINANCE_ALPHA | 12 | 12 | ||||
GL_LUMINANCE16_ALPHA16 | GL_LUMINANCE_ALPHA | 16 | 16 | ||||
GL_INTENSITY4 | GL_INTENSITY | 4 | |||||
GL_INTENSITY8 | GL_INTENSITY | 8 | |||||
GL_INTENSITY12 | GL_INTENSITY | 12 | |||||
GL_INTENSITY16 | GL_INTENSITY | 16 | |||||
GL_R3_G3_B2 | GL_RGB | 3 | 3 | 2 | |||
GL_RGB4 | GL_RGB | 4 | 4 | 4 | |||
GL_RGB5 | GL_RGB | 5 | 5 | 5 | |||
GL_RGB8 | GL_RGB | 8 | 8 | 8 | |||
GL_RGB10 | GL_RGB | 10 | 10 | 10 | |||
GL_RGB12 | GL_RGB | 12 | 12 | 12 | |||
GL_RGB16 | GL_RGB | 16 | 16 | 16 | |||
GL_RGBA2 | GL_RGBA | 2 | 2 | 2 | 2 | ||
GL_RGBA4 | GL_RGBA | 4 | 4 | 4 | 4 | ||
GL_RGB5_A1 | GL_RGBA | 5 | 5 | 5 | 1 | ||
GL_RGBA8 | GL_RGBA | 8 | 8 | 8 | 8 | ||
GL_RGB10_A2 | GL_RGBA | 10 | 10 | 10 | 2 | ||
GL_RGBA12 | GL_RGBA | 12 | 12 | 12 | 12 | ||
GL_RGBA16 | GL_RGBA | 16 | 16 | 16 | 16 |
Pro šetření pamětí jsou zajímavé například formáty GL_R3_G3_B2, kdy paměť pro jeden texel zabírá pouze jeden byte, nebo GL_RGB5_A1, kde každá barvová složka zabírá 5 bitů (celkem je tedy pro barvu vyhrazeno 15 bitů) a alfa složka jeden bit (rozlišujeme tedy pouze průhlednost či neprůhlednost texelu).
4. Třída TextureFactory a objekt typu Texture
Grafická knihovna OpenGL neobsahuje žádné funkce pro načtení textury ze souboru či ke konverzím mezi různými formáty pixelů/texelů. Programátoři využívající pouze OpenGL tedy musí příslušný programový kód napsat ručně, ovšem vzhledem k tomu, že se jedná stále o stejné operace, existuje v knihovně SDLJava dvojice tříd, které dokážou texturu načíst a posléze s ní jednoduše pracovat. První z těchto tříd se jmenuje org.gljava.opengl.TextureFactory a najdeme v ní jak statickou metodu getFactory() vracející instanci této třídy (konstruktor není viditelný), tak i trojici metod loadTexture() pro načtení textury z externího souboru, popř. z obrázku typu BufferedImage (což se může hodit v případě, že je textura například vytvořena procedurálně):
# | Návratový typ | Metoda | Popis |
---|---|---|---|
1 | TextureFactory | getFactory() | získání instance třídy TextureFactory |
2 | Texture | loadTexture(GL gl, java.lang.String path) | načtení textury ze souboru specifikovaného jménem |
3 | Texture | loadTexture(GL gl, java.net.URL url) | načtení textury ze souboru/zdroje specifikovaného URL |
4 | Texture | loadTexture(GL gl, java.awt.image.BufferedImage bufferedImage, int target, int dstPixelFormat, int minFilter, int magFilter) | načtení textury z obrázku typu BufferedImage |
Návratovou hodnotou metod TextureFactory.loadTexture() je instance třídy typu org.gljava.opengl.Texture, která představuje texturu použitelnou při vykreslování objektů. Velmi důležitou metodou, kterou musíme při vykreslování použít, je Texture.bind() sloužící pro navázání textury na kontext OpenGL. Dále tato třída obsahuje metody pro zjištění rozměrů textury, popř. pro nastavení těchto rozměrů:
# | Návratový typ | Metoda | Popis |
---|---|---|---|
1 | void | bind(GL gl) | nejdůležitější metoda, navázání textury na kontext OpenGL |
2 | float | getWidth() | zjištění skutečné šířky textury |
3 | float | getHeight() | zjištění skutečné výšky textury |
4 | int | getImageWidth() | zjištění šířky pixmapy (v pixelech) |
5 | int | getImageHeight() | zjištění výšky pixmapy (v pixelech) |
5. Demonstrační příklad SDLTest20 – texturování a objekt typu Texture
V dnešním prvním demonstračním příkladu nazvaném SDLTest20 je ukázána základní práce s texturami. Ihned po inicializaci knihovny SDLJava, nastavení grafického režimu a získání kontextu OpenGL je načten rastrový obrázek „xscorch.bmp“, který si můžete stáhnout z této adresy. Tento obrázek je reprezentován instancí třídy Texture, která bude následně použita při vykreslování:
// nacteni textury Texture texture = TextureFactory.getFactory().loadTexture(gl, "xscorch.bmp");
Následně je nutné nastavit základní parametry texturování, což jsou operace prováděné přes knihovnu OpenGL. Texturování je nejprve potřeba povolit a poté nastavit režim opakování textury, filtry použité při zvětšování či zmenšování textury a režim vykreslování při použití perspektivní projekce (resp. při určení čtvrté souřadnice vrcholů):
// povoleni prace s texturami gl.glEnable(gl.GL_TEXTURE_2D); // opakovani textury gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT); // volba filtru gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST); // vylepseni zobrazovani v pripade pouziti perspektivni projekce gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST);
Při vykreslování je zapotřebí nejdříve určit, která textura se má použít, což se provede navázáním textury na kontext OpenGL (změní se tím vnitřní stav OpenGL):
texture.bind(gl);
Při vykreslování objektu je nutné u každého vertexu určit i souřadnice v prostoru textury (u-v souřadnice):
// vykresleni ctyruhelniku gl.glBegin(gl.GL_QUADS); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex2i(200, 100); gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex2i(600, 100); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex2i(600, 300); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex2i(200, 600); gl.glEnd();
Následuje úplný výpis programového kódu tohoto demonstračního příkladu:
import java.nio.ByteBuffer; import java.nio.ByteOrder; import sdljava.SDLMain; import sdljava.SDLException; import sdljava.video.SDLPixelFormat; import sdljava.video.SDLSurface; import sdljava.video.SDLVideo; import org.gljava.opengl.GL; import org.gljava.opengl.Texture; import org.gljava.opengl.TextureFactory; /** * Dvacaty demonstracni priklad vyuzivajici knihovnu SDLjava. * * Texturovani a objekt typu Texture. * * @author Pavel Tisnovsky */ public class SDLTest20 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 200; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 200; /** * Bitova hloubka vybraneho grafickeho rezimu. * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty) */ private static final int GFX_BPP = 0; /** * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani. */ private static SDLSurface initVideo() throws SDLException { final long flags = SDLVideo.SDL_OPENGL | SDLVideo.SDL_DOUBLEBUF; return SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Nastaveni transformacnich matic a barvy pozadi framebufferu. */ private static void initScene(GL gl, int width, int height) { // nastaveni projekcni matice gl.glMatrixMode(gl.GL_PROJECTION); // jednotkova matice gl.glLoadIdentity(); // mapovani abstraktnich souradnic do souradnic okna ci cele obrazovky gl.glOrtho(0, width, height, 0, -1, 1); // nastaveni modelview matice gl.glMatrixMode(gl.GL_MODELVIEW); gl.glLoadIdentity(); // viditelna oblast gl.glViewport(0, 0, width, height); // vypnuti pameti hloubky pri vykreslovani gl.glDisable(gl.GL_DEPTH_TEST); // povoleni prace s texturami gl.glEnable(gl.GL_TEXTURE_2D); // opakovani textury gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT); // volba filtru gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST); // vylepseni zobrazovani v pripade pouziti perspektivni projekce gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST); // barva pozadi framebufferu pro volani glClear() gl.glClearColor (0.0f, 0.0f, 0.0f, 0.0f); } /** * Vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL. */ private static void drawScene(GL gl, Texture texture) { // vymazani framebufferu gl.glClear(gl.GL_COLOR_BUFFER_BIT); texture.bind(gl); // vykresleni ctyruhelniku gl.glBegin(gl.GL_QUADS); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex2i(200, 100); gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex2i(600, 100); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex2i(600, 300); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex2i(200, 600); gl.glEnd(); gl.glFlush(); // provedeni a vykresleni vsech zmen } /** * Spusteni osmeho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace video subsystemu knihovny SDL SDLMain.init(SDLMain.SDL_INIT_VIDEO); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani SDLSurface screen = initVideo(); // inicializace celoobrazovkoveho grafickeho rezimu GL gl = screen.getGL(); // nastaveni transformacnich matic a barvy pozadi framebufferu initScene(gl, GFX_WIDTH, GFX_HEIGHT); // nacteni textury Texture texture = TextureFactory.getFactory().loadTexture(gl, "xscorch.bmp"); // vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL drawScene(gl, texture); // prepnuti predniho a zadniho bufferu screen.glSwapBuffers(); // ukonceni cele aplikace po peti sekundach Thread.sleep(5000); } catch (Exception e) { e.printStackTrace(); } finally { // musime obnovit puvodni graficky rezim // i v tom pripade, ze nastane nejaka vyjimka SDLMain.quit(); } // zobrazit ziskane informace } }
Skript pro překlad na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest20.java
Dávkový soubor pro překlad na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest20.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest20
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest20
Obrázek 1: Scéna vykreslená po spuštění demonstračního příkladu SDLTest20.
6. Demonstrační příklad SDLTest21 – opakování textury
Dnešní druhý demonstrační příklad má název SDLTest21 a je na něm ukázán efekt opakování textury v případě, že souřadnice v prostoru textury překračují interval 0.0 až 1.0. Nastavení grafického režimu, inicializace OpenGL se získáním kontextu OpenGL i načtení textury probíhá zcela stejným způsobem, jako tomu bylo v předchozím příkladu. Stejné je i nastavení parametrů texturování:
// povoleni prace s texturami gl.glEnable(gl.GL_TEXTURE_2D); // opakovani textury gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT); // volba filtru gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST); // vylepseni zobrazovani v pripade pouziti perspektivni projekce gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST);
Při vlastním vykreslování jsou však zadány souřadnice v prostoru textury, které v některých případech leží mimo rozsah 0.0 až 1.0, což znamená, že grafický akcelerátor bude texturu nanášet na objekt opakovaně (jakoby se jednalo o dlaždice). V následujícím úryvku kódu si všimněte parametrů předávaných do metody gl.glTexCoord2f():
// vykresleni ctyruhelniku gl.glBegin(gl.GL_QUADS); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex2i(200, 100); gl.glTexCoord2f(3.0f, 0.0f); gl.glVertex2i(600, 100); gl.glTexCoord2f(1.0f, 3.0f); gl.glVertex2i(600, 300); gl.glTexCoord2f(-1.0f, 1.0f); gl.glVertex2i(100, 600); gl.glEnd();
Úplný výpis demonstračního příkladu SDLTest21 je zobrazen pod tímto odstavcem:
import java.nio.ByteBuffer; import java.nio.ByteOrder; import sdljava.SDLMain; import sdljava.SDLException; import sdljava.video.SDLPixelFormat; import sdljava.video.SDLSurface; import sdljava.video.SDLVideo; import org.gljava.opengl.GL; import org.gljava.opengl.Texture; import org.gljava.opengl.TextureFactory; /** * Dvacaty prvni demonstracni priklad vyuzivajici knihovnu SDLjava. * * Texturovani a objekt typu Texture - opakovani textury. * * @author Pavel Tisnovsky */ public class SDLTest21 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 200; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 200; /** * Bitova hloubka vybraneho grafickeho rezimu. * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty) */ private static final int GFX_BPP = 0; /** * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani. */ private static SDLSurface initVideo() throws SDLException { final long flags = SDLVideo.SDL_OPENGL | SDLVideo.SDL_DOUBLEBUF; return SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Nastaveni transformacnich matic a barvy pozadi framebufferu. */ private static void initScene(GL gl, int width, int height) { // nastaveni projekcni matice gl.glMatrixMode(gl.GL_PROJECTION); // jednotkova matice gl.glLoadIdentity(); // mapovani abstraktnich souradnic do souradnic okna ci cele obrazovky gl.glOrtho(0, width, height, 0, -1, 1); // nastaveni modelview matice gl.glMatrixMode(gl.GL_MODELVIEW); gl.glLoadIdentity(); // viditelna oblast gl.glViewport(0, 0, width, height); // vypnuti pameti hloubky pri vykreslovani gl.glDisable(gl.GL_DEPTH_TEST); // povoleni prace s texturami gl.glEnable(gl.GL_TEXTURE_2D); // opakovani textury gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT); // volba filtru gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST); // vylepseni zobrazovani v pripade pouziti perspektivni projekce gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST); // barva pozadi framebufferu pro volani glClear() gl.glClearColor (0.0f, 0.0f, 0.0f, 0.0f); } /** * Vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL. */ private static void drawScene(GL gl, Texture texture) { // vymazani framebufferu gl.glClear(gl.GL_COLOR_BUFFER_BIT); texture.bind(gl); // vykresleni ctyruhelniku gl.glBegin(gl.GL_QUADS); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex2i(200, 100); gl.glTexCoord2f(3.0f, 0.0f); gl.glVertex2i(600, 100); gl.glTexCoord2f(1.0f, 3.0f); gl.glVertex2i(600, 300); gl.glTexCoord2f(-1.0f, 1.0f); gl.glVertex2i(100, 600); gl.glEnd(); gl.glFlush(); // provedeni a vykresleni vsech zmen } /** * Spusteni osmeho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace video subsystemu knihovny SDL SDLMain.init(SDLMain.SDL_INIT_VIDEO); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani SDLSurface screen = initVideo(); // inicializace celoobrazovkoveho grafickeho rezimu GL gl = screen.getGL(); // nastaveni transformacnich matic a barvy pozadi framebufferu initScene(gl, GFX_WIDTH, GFX_HEIGHT); // nacteni textury Texture texture = TextureFactory.getFactory().loadTexture(gl, "xscorch.bmp"); // vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL drawScene(gl, texture); // prepnuti predniho a zadniho bufferu screen.glSwapBuffers(); // ukonceni cele aplikace po peti sekundach Thread.sleep(5000); } catch (Exception e) { e.printStackTrace(); } finally { // musime obnovit puvodni graficky rezim // i v tom pripade, ze nastane nejaka vyjimka SDLMain.quit(); } // zobrazit ziskane informace } }
Skript pro překlad na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest21.java
Dávkový soubor pro překlad na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest21.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest21
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest21
Obrázek 1: Scéna vykreslená po spuštění demonstračního příkladu SDLTest21.
7. Demonstrační příklad SDLTest22 – protažení textury
Při zvětšení či naopak zmenšení textury se začínají uplatňovat filtry prováděné grafickým akcelerátorem. Filtry se nepoužijí pouze v jednom případě – když je velikost pixelů a texelů zcela shodná a současně se plochy pixelů a texelů přesně překrývají (objekt není natočen ani posunut oproti souřadnému systému obrazovky). Prozatím jsme si neřekli bližší informace o takzvaném mipmappingu, ovšem i bez využití této technologie lze zvolit minimálně mezi dvěma typy filtrů: velmi rychlý filtr typu „nearest“, který vždy vybere barvu nejbližšího texelu a poněkud pomalejší (více přístupů do texturovací paměti) filtr provádějící (bili)neární interpolaci na základě barev přečtených z nejbližších texelů. V dnešním posledním demonstračním příkladu je ukázán rozdíl mezi těmito filtry.
Objekt, v našem případě jednoduchý obdélník, je vykreslen dvakrát. Jednou s využitím filtru typu „nearest“:
// volba filtru gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST); // vykresleni ctyruhelniku gl.glBegin(gl.GL_QUADS); gl.glTexCoord2f(0.0f, 0.3f); gl.glVertex2i(0, 0); gl.glTexCoord2f(0.5f, 0.3f); gl.glVertex2i(300, 0); gl.glTexCoord2f(0.5f, 0.8f); gl.glVertex2i(300, 200); gl.glTexCoord2f(0.0f, 0.8f); gl.glVertex2i(0, 200); gl.glEnd();
A podruhé s využitím filtru provádějícího bilineární interpolaci:
// volba filtru gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR); texture.bind(gl); // vykresleni ctyruhelniku gl.glBegin(gl.GL_QUADS); gl.glTexCoord2f(0.0f, 0.3f); gl.glVertex2i(0, 200); gl.glTexCoord2f(0.5f, 0.3f); gl.glVertex2i(300, 200); gl.glTexCoord2f(0.5f, 0.8f); gl.glVertex2i(300, 400); gl.glTexCoord2f(0.0f, 0.8f); gl.glVertex2i(0, 400); gl.glEnd();
Následuje úplný výpis zdrojového kódu třetího demonstračního příkladu:
import java.nio.ByteBuffer; import java.nio.ByteOrder; import sdljava.SDLMain; import sdljava.SDLException; import sdljava.video.SDLPixelFormat; import sdljava.video.SDLSurface; import sdljava.video.SDLVideo; import org.gljava.opengl.GL; import org.gljava.opengl.Texture; import org.gljava.opengl.TextureFactory; /** * Dvacaty druhy demonstracni priklad vyuzivajici knihovnu SDLjava. * * Texturovani a objekt typu Texture - volba ruznych filtru pouzitych pri texturovani. * * @author Pavel Tisnovsky */ public class SDLTest22 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 300; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 400; /** * Bitova hloubka vybraneho grafickeho rezimu. * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty) */ private static final int GFX_BPP = 0; /** * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani. */ private static SDLSurface initVideo() throws SDLException { final long flags = SDLVideo.SDL_OPENGL | SDLVideo.SDL_DOUBLEBUF; return SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Nastaveni transformacnich matic a barvy pozadi framebufferu. */ private static void initScene(GL gl, int width, int height) { // nastaveni projekcni matice gl.glMatrixMode(gl.GL_PROJECTION); // jednotkova matice gl.glLoadIdentity(); // mapovani abstraktnich souradnic do souradnic okna ci cele obrazovky gl.glOrtho(0, width, height, 0, -1, 1); // nastaveni modelview matice gl.glMatrixMode(gl.GL_MODELVIEW); gl.glLoadIdentity(); // viditelna oblast gl.glViewport(0, 0, width, height); // vypnuti pameti hloubky pri vykreslovani gl.glDisable(gl.GL_DEPTH_TEST); // povoleni prace s texturami gl.glEnable(gl.GL_TEXTURE_2D); // opakovani textury gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT); // vylepseni zobrazovani v pripade pouziti perspektivni projekce gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST); // barva pozadi framebufferu pro volani glClear() gl.glClearColor (0.0f, 0.0f, 0.0f, 0.0f); } /** * Vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL. */ private static void drawScene(GL gl, Texture texture) { // vymazani framebufferu gl.glClear(gl.GL_COLOR_BUFFER_BIT); texture.bind(gl); // volba filtru gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST); // vykresleni ctyruhelniku gl.glBegin(gl.GL_QUADS); gl.glTexCoord2f(0.0f, 0.3f); gl.glVertex2i(0, 0); gl.glTexCoord2f(0.5f, 0.3f); gl.glVertex2i(300, 0); gl.glTexCoord2f(0.5f, 0.8f); gl.glVertex2i(300, 200); gl.glTexCoord2f(0.0f, 0.8f); gl.glVertex2i(0, 200); gl.glEnd(); // volba filtru gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR); texture.bind(gl); // vykresleni ctyruhelniku gl.glBegin(gl.GL_QUADS); gl.glTexCoord2f(0.0f, 0.3f); gl.glVertex2i(0, 200); gl.glTexCoord2f(0.5f, 0.3f); gl.glVertex2i(300, 200); gl.glTexCoord2f(0.5f, 0.8f); gl.glVertex2i(300, 400); gl.glTexCoord2f(0.0f, 0.8f); gl.glVertex2i(0, 400); gl.glEnd(); gl.glFlush(); // provedeni a vykresleni vsech zmen } /** * Spusteni osmeho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace video subsystemu knihovny SDL SDLMain.init(SDLMain.SDL_INIT_VIDEO); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani SDLSurface screen = initVideo(); // inicializace celoobrazovkoveho grafickeho rezimu GL gl = screen.getGL(); // nastaveni transformacnich matic a barvy pozadi framebufferu initScene(gl, GFX_WIDTH, GFX_HEIGHT); // nacteni textury Texture texture = TextureFactory.getFactory().loadTexture(gl, "xscorch.bmp"); // vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL drawScene(gl, texture); // prepnuti predniho a zadniho bufferu screen.glSwapBuffers(); // ukonceni cele aplikace po peti sekundach Thread.sleep(5000); } catch (Exception e) { e.printStackTrace(); } finally { // musime obnovit puvodni graficky rezim // i v tom pripade, ze nastane nejaka vyjimka SDLMain.quit(); } // zobrazit ziskane informace } }
Skript pro překlad na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest22.java
Dávkový soubor pro překlad na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest22.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest22
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest22
Obrázek 1: Scéna vykreslená po spuštění demonstračního příkladu SDLTest22.
8. Repositář se zdrojovými kódy všech tří dnešních demonstračních příkladů
Všechny tři dnes popsané demonstrační příklady byly společně s podpůrnými skripty určenými pro jejich překlad a následné spuštění uloženy do Mercurial repositáře dostupného na adrese http://icedtea.classpath.org/people/ptisnovs/jvm-tools/. Podobně jako tomu bylo i v předchozích pěti dílech tohoto seriálu, i ke dnešním příkladům jsou přiloženy skripty využitelné pro jejich překlad a spuštění. Navíc byly přidány i skripty využitelné ve Windows:
9. Odkazy na Internetu
- glDrawArrays
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArrays.xml - glDrawElements
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElements.xml - glDrawArraysInstanced
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArraysInstanced.xml - glDrawElementsInstanced
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElementsInstanced.xml - Root.cz: Seriál Grafická knihovna OpenGL
http://www.root.cz/serialy/graficka-knihovna-opengl/ - Root.cz: Seriál Tvorba přenositelných grafických aplikací využívajících knihovnu GLUT
http://www.root.cz/serialy/tvorba-prenositelnych-grafickych-aplikaci-vyuzivajicich-knihovnu-glut/ - Best Practices for Working with Vertex Data
https://developer.apple.com/library/ios/documentation/3ddrawing/conceptual/opengles_programmingguide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html - SDL 1.2 Documentation: SDL_Surface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsurface.html - SDL 1.2 Documentation: SDL_PixelFormat
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlpixelformat.html - SDL 1.2 Documentation: SDL_LockSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdllocksurface.html - SDL 1.2 Documentation: SDL_UnlockSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlunlocksurface.html - SDL 1.2 Documentation: SDL_LoadBMP
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlloadbmp.html - SDL 1.2 Documentation: SDL_SaveBMP
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsavebmp.html - SDL 1.2 Documentation: SDL_BlitSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlblitsurface.html - SDL 1.2 Documentation: SDL_VideoInfo
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlvideoinfo.html - SDL 1.2 Documentation: SDL_GetVideoInfo
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlgetvideoinfo.html - Class BufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/image/BufferStrategy.html - Class Graphics
http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Graphics.html - Double Buffering and Page Flipping
http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html - BufferStrategy and BufferCapabilities
http://docs.oracle.com/javase/tutorial/extra/fullscreen/bufferstrategy.html - Java:Tutorials:Double Buffering
http://content.gpwiki.org/index.php/Java:Tutorials:Double_Buffering - Double buffer in standard Java AWT
http://www.codeproject.com/Articles/2136/Double-buffer-in-standard-Java-AWT - Java 2D: Hardware Accelerating – Part 1 – Volatile Images
http://www.javalobby.org/forums/thread.jspa?threadID=16840&tstart=0 - Java 2D: Hardware Accelerating – Part 2 – Buffer Strategies
http://www.javalobby.org/java/forums/t16867.html - How does paintComponent work?
http://stackoverflow.com/questions/15544549/how-does-paintcomponent-work - A Swing Architecture Overview
http://www.oracle.com/technetwork/java/architecture-142923.html - Class javax.swing.JComponent
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html - Class java.awt.Component
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.html - Class java.awt.Component.BltBufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.BltBufferStrategy.html - Class java.awt.Component.FlipBufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.FlipBufferStrategy.html - Metoda java.awt.Component.isDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.html#isDoubleBuffered() - Metoda javax.swing.JComponent.isDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#isDoubleBuffered() - Metoda javax.swing.JComponent.setDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#setDoubleBuffered(boolean) - Javadoc – třída GraphicsDevice
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsDevice.html - Javadoc – třída GraphicsEnvironment
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsEnvironment.html - Javadoc – třída GraphicsConfiguration
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsConfiguration.html - Javadoc – třída DisplayMode
http://docs.oracle.com/javase/7/docs/api/java/awt/DisplayMode.html - Lesson: Full-Screen Exclusive Mode API
http://docs.oracle.com/javase/tutorial/extra/fullscreen/ - Full-Screen Exclusive Mode
http://docs.oracle.com/javase/tutorial/extra/fullscreen/exclusivemode.html - Display Mode
http://docs.oracle.com/javase/tutorial/extra/fullscreen/displaymode.html - Using the Full-Screen Exclusive Mode API in Java
http://www.developer.com/java/other/article.php/3609776/Using-the-Full-Screen-Exclusive-Mode-API-in-Java.htm - Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
http://www.mobilefish.com/tutorials/java/java_quickguide_jvm_instruction_set.html - The JVM Instruction Set
http://mpdeboer.home.xs4all.nl/scriptie/node14.html - MultiMedia eXtensions
http://softpixel.com/~cwright/programming/simd/mmx.phpi - SSE (Streaming SIMD Extentions)
http://www.songho.ca/misc/sse/sse.html - Timothy A. Chagnon: SSE and SSE2
http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf - Intel corporation: Extending the Worldr's Most Popular Processor Architecture
http://download.intel.com/technology/architecture/new-instructions-paper.pdf - SIMD architectures:
http://arstechnica.com/old/content/2000/03/simd.ars/ - GC safe-point (or safepoint) and safe-region
http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html - Safepoints in HotSpot JVM
http://blog.ragozin.info/2012/10/safepoints-in-hotspot-jvm.html - Java theory and practice: Synchronization optimizations in Mustang
http://www.ibm.com/developerworks/java/library/j-jtp10185/ - How to build hsdis
http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/tip/src/share/tools/hsdis/README - Java SE 6 Performance White Paper
http://www.oracle.com/technetwork/java/6-performance-137236.html - Lukas Stadler's Blog
http://classparser.blogspot.cz/2010/03/hsdis-i386dll.html - How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
http://dropzone.nfshost.com/hsdis.htm - PrintAssembly
https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly - The Java Virtual Machine Specification: 3.14. Synchronization
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.14 - The Java Virtual Machine Specification: 8.3.1.4. volatile Fields
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.4 - The Java Virtual Machine Specification: 17.4. Memory Model
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4 - The Java Virtual Machine Specification: 17.7. Non-atomic Treatment of double and long
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7 - Open Source ByteCode Libraries in Java
http://java-source.net/open-source/bytecode-libraries - ASM Home page
http://asm.ow2.org/ - Seznam nástrojů využívajících projekt ASM
http://asm.ow2.org/users.html - ObjectWeb ASM (Wikipedia)
http://en.wikipedia.org/wiki/ObjectWeb_ASM - Java Bytecode BCEL vs ASM
http://james.onegoodcookie.com/2005/10/26/java-bytecode-bcel-vs-asm/ - BCEL Home page
http://commons.apache.org/bcel/ - Byte Code Engineering Library (před verzí 5.0)
http://bcel.sourceforge.net/ - Byte Code Engineering Library (verze >= 5.0)
http://commons.apache.org/proper/commons-bcel/ - BCEL Manual
http://commons.apache.org/bcel/manual.html - Byte Code Engineering Library (Wikipedia)
http://en.wikipedia.org/wiki/BCEL - BCEL Tutorial
http://www.smfsupport.com/support/java/bcel-tutorial!/ - Bytecode Engineering
http://book.chinaunix.net/special/ebook/Core_Java2_Volume2AF/0131118269/ch13lev1sec6.html - Bytecode Outline plugin for Eclipse (screenshoty + info)
http://asm.ow2.org/eclipse/index.html - Javassist
http://www.jboss.org/javassist/ - Byteman
http://www.jboss.org/byteman - Java programming dynamics, Part 7: Bytecode engineering with BCEL
http://www.ibm.com/developerworks/java/library/j-dyn0414/ - The JavaTM Virtual Machine Specification, Second Edition
http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html - The class File Format
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html - javap – The Java Class File Disassembler
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/javap.html - javap-java-1.6.0-openjdk(1) – Linux man page
http://linux.die.net/man/1/javap-java-1.6.0-openjdk - Using javap
http://www.idevelopment.info/data/Programming/java/miscellaneous_java/Using_javap.html - Examine class files with the javap command
http://www.techrepublic.com/article/examine-class-files-with-the-javap-command/5815354 - aspectj (Eclipse)
http://www.eclipse.org/aspectj/ - Aspect-oriented programming (Wikipedia)
http://en.wikipedia.org/wiki/Aspect_oriented_programming - AspectJ (Wikipedia)
http://en.wikipedia.org/wiki/AspectJ - EMMA: a free Java code coverage tool
http://emma.sourceforge.net/ - Cobertura
http://cobertura.sourceforge.net/ - jclasslib bytecode viewer
http://www.ej-technologies.com/products/jclasslib/overview.html