Obsah
1. Dokončení tématu z předchozí části seriálu: obrázky typu BufferedImage a texturování
2. Parametry metody TextureFactory.loadTexture()
3. Demonstrační příklad SDLTest26 – použití obrázku typu BufferedImage při texturování
4. Demonstrační příklad SDLTest27 – BufferedImage, texturování a alfa blending
5. Zpracování událostí v knihovně SDLJava
6. Demonstrační příklad SDLTest28 – čtení událostí ve smyčce
7. Demonstrační příklad SDLTest29 – reakce na událost typu SDLQuitEvent
8. Demonstrační příklad SDLTest30 – čtení informací o stisknutých a puštěných klávesách
9. Repositář se zdrojovými kódy všech pěti dnešních demonstračních příkladů
1. Dokončení tématu z předchozí části seriálu: obrázky typu BufferedImage a texturování
V dnešní části seriálu o programovacím jazyce Java i o virtuálním stroji tohoto jazyka se budeme zabývat především popisem zpracování událostí v knihovně SDLJava. Ještě předtím však musíme dokončit téma, kterému jsme se věnovali v poslední i předposlední části tohoto seriálu – texturování. Na několika demonstračních příkladech jsme si již ukázali, jakým způsobem je možné načíst texturu z externího souboru a jak se následně tato textura naváže na kontext OpenGL. Ovšem v knihovně SDLJava je možné texturu, přesněji řečeno instanci třídy Texture vytvořit i z rastrového obrázku typu BufferedImage. Tato funkcionalita se může hodit zejména ve chvílích, kdy je obrázek nějakým způsobem programově generován, tj. když je například vytvářena procedurální textura. Základem pro vytváření či načítání textur je třída org.gljava.opengl.TextureFactory, která mj. nabízí i následující metody určené pro získání instance této třídy a následně pro načtení textury:
# | 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 |
2. Parametry metody TextureFactory.loadTexture()
Nás nyní bude zajímat především poslední zmíněná metoda TextureFactory.loadTexture(GL gl, java.awt.image.BufferedImage bufferedImage, int target, int dstPixelFormat, int minFilter, int magFilter), které je možné předat obrázek typu BufferedImage a na základě dalších informací se z tohoto obrázku vytvoří běžná textura, tj. objekt typu Texture. Význam parametrů této metody je následující:
# | Parametr | Význam |
---|---|---|
1 | GL gl | aktuální kontext OpenGL |
2 | BufferedImage bufferedImage | obrázek, který má být konvertován na texturu |
3 | int target | buď GL.GL_TEXTURE_1D nebo GL.GL_TEXTURE_2D |
4 | int dstPixelFormat | formát textury, typicky GL.GL_RGBA (viz též předchozí části tohoto seriálu) |
5 | int minFilter | filtr použitý při zmenšování obrázku, typicky GL.GL_LINEAR |
6 | int magFilter | filtr použitý při zvětšování obrázku, typicky GL.GL_LINEAR |
Parametr target může podle typu textury nabývat hodnot:
# | Hodnota | Význam |
---|---|---|
1 | GL.GL_TEXTURE_1D | jednorozměrná textura |
2 | GL.GL_TEXTURE_2D | dvourozměrná textura (mnohem častější) |
Parametr dstPixelFormat určuje interní formát výsledné textury:
# | Rozšířený formát | Základní formát |
---|---|---|
1 | GL_ALPHA4 | GL_ALPHA |
2 | GL_ALPHA8 | GL_ALPHA |
3 | GL_ALPHA12 | GL_ALPHA |
4 | GL_ALPHA16 | GL_ALPHA |
5 | GL_LUMINANCE4 | GL_LUMINANCE |
6 | GL_LUMINANCE8 | GL_LUMINANCE |
7 | GL_LUMINANCE12 | GL_LUMINANCE |
8 | GL_LUMINANCE16 | GL_LUMINANCE |
9 | GL_LUMINANCE4_ALPHA4 | GL_LUMINANCE_ALPHA |
10 | GL_LUMINANCE6_ALPHA2 | GL_LUMINANCE_ALPHA |
11 | GL_LUMINANCE8_ALPHA8 | GL_LUMINANCE_ALPHA |
12 | GL_LUMINANCE12_ALPHA4 | GL_LUMINANCE_ALPHA |
13 | GL_LUMINANCE12_ALPHA12 | GL_LUMINANCE_ALPHA |
14 | GL_LUMINANCE16_ALPHA16 | GL_LUMINANCE_ALPHA |
15 | GL_INTENSITY4 | GL_INTENSITY |
16 | GL_INTENSITY8 | GL_INTENSITY |
17 | GL_INTENSITY12 | GL_INTENSITY |
18 | GL_INTENSITY16 | GL_INTENSITY |
19 | GL_R3_G3_B2 | GL_RGB |
20 | GL_RGB4 | GL_RGB |
21 | GL_RGB5 | GL_RGB |
22 | GL_RGB8 | GL_RGB |
23 | GL_RGB10 | GL_RGB |
24 | GL_RGB12 | GL_RGB |
25 | GL_RGB16 | GL_RGB |
26 | GL_RGBA2 | GL_RGBA |
27 | GL_RGBA4 | GL_RGBA |
28 | GL_RGB5_A1 | GL_RGBA |
29 | GL_RGBA8 | GL_RGBA |
30 | GL_RGB10_A2 | GL_RGBA |
31 | GL_RGBA12 | GL_RGBA |
32 | GL_RGBA16 | GL_RGBA |
Hodnoty předávané v posledních dvou parametrech minFilter a magFilter jsou specifikovány těmito konstantami:
# | Hodnota | Význam |
---|---|---|
1 | GL.GL_NEAREST | při změně velikosti se použije nejbližší texel |
2 | GL.GL_LINEAR | při změně velikosti se použije (bi)lineární interpolace |
3. Demonstrační příklad SDLTest26 – použití obrázku typu BufferedImage při texturování
V dnešním prvním demonstračním příkladu, který se jmenuje SDLTest26, je ukázáno, jak je možné vytvořit texturu, tj. instanci třídy org.gljava.opengl.Texture z rastrového obrázku (bitmapy) reprezentovaného objektem typu java.awt.image.BufferedImage. Vlastní bitmapa je vytvořena v metodě createTexture(), přičemž si všimněte, že formát uložení pixelů v bitmapě může, ale nemusí přesně korespondovat s formátem uložení pixelů ve výsledné textuře. Následně je bitmapa v metodě renderImage() vyplněna jednoduchým vzorkem a poté je provedeno její převedení na texturu. Rozměry textury samozřejmě nemusí korespondovat s rozměry reálného objektu, který je touto texturou pokryt:
/** * Vytvoreni textury z obrazku typu BufferedImage. */ private static Texture createTexture(GL gl) throws IOException { // rozmery textury final int width = 256; final int height = 256; // vytvoreni rastroveho obrazku BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); renderImage(image); // ziskani instance typu TextureFactory TextureFactory textureFactory = TextureFactory.getFactory(); // vytvoreni textury z obrazku typu BufferedImage return textureFactory.loadTexture(gl, image, GL.GL_TEXTURE_2D, GL.GL_RGBA, GL.GL_LINEAR, GL.GL_LINEAR); }
Následuje výpis zdrojového kódu demonstračního příkladu SDLTest26:
import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.awt.image.DataBuffer; import java.io.IOException; 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 sesty demonstracni priklad vyuzivajici knihovnu SDLjava. * * Vytvoreni textury z obrazku typu BufferedImage. * * @author Pavel Tisnovsky */ public class SDLTest26 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 600; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 600; /** * 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); // zakaz opakovani textury gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP); // 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); // zakaz prace s texturami gl.glDisable(gl.GL_TEXTURE_2D); gl.glBegin(GL.GL_LINES); gl.glColor3f(1.0f, 0.0f, 0.0f); gl.glVertex2i(0, 0); gl.glColor3f(1.0f, 0.0f, 1.0f); gl.glVertex2i(600, 600); gl.glColor3f(0.0f, 1.0f, 0.0f); gl.glVertex2i(600, 0); gl.glColor3f(1.0f, 1.0f, 0.0f); gl.glVertex2i(0, 600); gl.glEnd(); // povoleni prace s texturami gl.glEnable(GL.GL_TEXTURE_2D); // navazani textury na kontext OpenGL texture.bind(gl); // vykresleni ctyruhelniku pokryteho texturou gl.glBegin(GL.GL_QUADS); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex2i(100, 100); gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex2i(500, 100); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex2i(500, 500); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex2i(100, 500); gl.glEnd(); gl.glFlush(); // provedeni a vykresleni vsech zmen } /** * Vytvoreni textury z obrazku typu BufferedImage. */ private static Texture createTexture(GL gl) throws IOException { // rozmery textury final int width = 256; final int height = 256; // vytvoreni rastroveho obrazku BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); renderImage(image); // ziskani instance typu TextureFactory TextureFactory textureFactory = TextureFactory.getFactory(); // vytvoreni textury z obrazku typu BufferedImage return textureFactory.loadTexture(gl, image, GL.GL_TEXTURE_2D, GL.GL_RGBA, GL.GL_LINEAR, GL.GL_LINEAR); } /** * Vytvoreni vzorku. */ private static void renderImage(BufferedImage image) { // rozmery bitmapy final int width = image.getWidth(); final int height = image.getHeight(); // ziskani objektu obsahujiciho hodnoty vsech pixelu bitmapy DataBuffer dataBuffer = image.getRaster().getDataBuffer(); // provest vypocet barev pixelu a jejich vykresleni int i = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { dataBuffer.setElem(i++, 0xff); dataBuffer.setElem(i++, 0xff); dataBuffer.setElem(i++, y); dataBuffer.setElem(i++, x); } } System.out.println("Written " + i + " bytes into DataBuffer"); } /** * 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); // vytvoreni textury z obrazku typu BufferedImage Texture texture = createTexture(gl); // 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 SDLTest26.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 SDLTest26.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 SDLTest26
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% SDLTest26

Obrázek 1: Scéna vykreslená po spuštění demonstračního příkladu SDLTest26.
4. Demonstrační příklad SDLTest27 – BufferedImage, texturování a alfa blending
V předchozí části tohoto seriálu jsme si ukázali, že v případě použití rastrového obrázku uloženého v souboru typu PNG je možné pro vytvoření textury v plné míře využít informace o průhlednosti jednotlivých pixelů uložených v alfa kanále (jedná se o volitelný kanál). Stejným způsobem je však možné pracovat s průhledností ve chvíli, kdy se textura vytváří z bitmapy typu BufferedImage, což je ukázáno v dnešním druhém demonstračním příkladu. Nejzajímavější je zde metoda drawScene(), z níž je patrné, že se nejdříve vykreslí pozadí složené z mřížky (alfa blending je vypnutý) a posléze se přes toho pozadí vykreslí poloprůhledná textura (nyní již se zapnutým alfa blendingem):
/** * Vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL. */ private static void drawScene(GL gl, Texture texture) { // vymazani framebufferu (bile pozadi) gl.glClear(GL.GL_COLOR_BUFFER_BIT); // zakaz prace s texturami gl.glDisable(gl.GL_TEXTURE_2D); // zakaz blendingu gl.glDisable(GL.GL_BLEND); // vykresleni mrizky gl.glColor3f(0.0f, 0.0f, 0.0f); gl.glBegin(GL.GL_LINES); for (int i=0; i < GFX_WIDTH; i+=20) { gl.glVertex2i(i, 0); gl.glVertex2i(i, GFX_HEIGHT); } for (int i=0; i < GFX_HEIGHT; i+=20) { gl.glVertex2i(0, i); gl.glVertex2i(GFX_WIDTH, i); } gl.glEnd(); // povoleni prace s texturami gl.glEnable(GL.GL_TEXTURE_2D); // povoleni a nastaveni blendingu gl.glEnable(GL.GL_BLEND); gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); // navazani textury na kontext OpenGL texture.bind(gl); // vykresleni ctyruhelniku pokryteho texturou gl.glBegin(GL.GL_QUADS); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex2i(100, 100); gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex2i(500, 100); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex2i(500, 500); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex2i(100, 500); gl.glEnd(); gl.glFlush(); // provedeni a vykresleni vsech zmen }
Opět následuje výpis úplného zdrojového kódu tohoto demonstračního příkladu:
import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.awt.image.DataBuffer; import java.io.IOException; 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 sedmy demonstracni priklad vyuzivajici knihovnu SDLjava. * * Vytvoreni textury z obrazku typu BufferedImage. * * @author Pavel Tisnovsky */ public class SDLTest27 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 600; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 600; /** * 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); // zakaz opakovani textury gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP); // 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 (1.0f, 1.0f, 1.0f, 0.0f); } /** * Vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL. */ private static void drawScene(GL gl, Texture texture) { // vymazani framebufferu (bile pozadi) gl.glClear(GL.GL_COLOR_BUFFER_BIT); // zakaz prace s texturami gl.glDisable(gl.GL_TEXTURE_2D); // zakaz blendingu gl.glDisable(GL.GL_BLEND); // vykresleni mrizky gl.glColor3f(0.0f, 0.0f, 0.0f); gl.glBegin(GL.GL_LINES); for (int i=0; i < GFX_WIDTH; i+=20) { gl.glVertex2i(i, 0); gl.glVertex2i(i, GFX_HEIGHT); } for (int i=0; i < GFX_HEIGHT; i+=20) { gl.glVertex2i(0, i); gl.glVertex2i(GFX_WIDTH, i); } gl.glEnd(); // povoleni prace s texturami gl.glEnable(GL.GL_TEXTURE_2D); // povoleni a nastaveni blendingu gl.glEnable(GL.GL_BLEND); gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); // navazani textury na kontext OpenGL texture.bind(gl); // vykresleni ctyruhelniku pokryteho texturou gl.glBegin(GL.GL_QUADS); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex2i(100, 100); gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex2i(500, 100); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex2i(500, 500); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex2i(100, 500); gl.glEnd(); gl.glFlush(); // provedeni a vykresleni vsech zmen } /** * Vytvoreni textury z obrazku typu BufferedImage. */ private static Texture createTexture(GL gl) throws IOException { // rozmery textury final int width = 256; final int height = 256; // vytvoreni rastroveho obrazku BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); renderImage(image); // ziskani instance typu TextureFactory TextureFactory textureFactory = TextureFactory.getFactory(); // vytvoreni textury z obrazku typu BufferedImage return textureFactory.loadTexture(gl, image, GL.GL_TEXTURE_2D, GL.GL_RGBA, GL.GL_LINEAR, GL.GL_LINEAR); } /** * Vytvoreni vzorku. */ private static void renderImage(BufferedImage image) { // rozmery bitmapy final int width = image.getWidth(); final int height = image.getHeight(); // ziskani objektu obsahujiciho hodnoty vsech pixelu bitmapy DataBuffer dataBuffer = image.getRaster().getDataBuffer(); // provest vypocet barev pixelu a jejich vykresleni int i = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { dataBuffer.setElem(i++, x+y); dataBuffer.setElem(i++, x-y); dataBuffer.setElem(i++, y); dataBuffer.setElem(i++, y); } } System.out.println("Written " + i + " bytes into DataBuffer"); } /** * 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); // vytvoreni textury z obrazku typu BufferedImage Texture texture = createTexture(gl); // 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 SDLTest27.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 SDLTest27.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 SDLTest27
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% SDLTest27

Obrázek 2: Scéna vykreslená po spuštění demonstračního příkladu SDLTest27.
5. Zpracování událostí v knihovně SDLJava
Knihovna SDLJava obsahuje i vlastní systém pro práci s událostmi, který je možné využít například při práci s klávesnicí, myší či joystickem. Systém událostí implementovaný v SDLJava se v několika ohledech odlišuje například od způsobu reakce na události, který známe z knihovny AWT a přeneseně i z knihovny Swing. Zatímco v případě AWT/Swing bylo možné naprogramovat reakci na nějaký typ události pro každou komponentu (okno, widget) zvlášť, a to formou anonymních tříd s „callback metodami“, je v SDLJava implementována jediná fronta událostí, z níž je možné jednotlivé události vybírat a/nebo číst s využitím následujících čtyř statických metod implementovaných ve třídě SDLEvent:
# | Metoda | Význam |
---|---|---|
1 | SDLEvent pollEvent() | přečtení události z fronty |
2 | SDLEvent pollEvent(boolean returnEvent) | přečtení události z fronty |
3 | SDLEvent waitEvent() | čekání na další událost a přečtení této události |
4 | SDLEvent waitEvent(boolean returnEvent) | čekání na další událost a případné přečtení této události |
To, zda se použije metoda pollEvent() či metoda waitEvent() závisí na povaze aplikace. Například ve chvíli, kdy aplikace zobrazuje nějaké menu či dialog, může být vhodné čekat na další událost v metodě waitEvent(), zatímco ve hře, v níž se pohybují protivníci nezávisle na akcích uživatele, se typicky používá metoda pollEvent(), která může vrátit null v případě, že žádná událost nebyla do fronty uložena.
V knihovně SDLJava je fronta událostí řešena takovým způsobem, aby se nemusely vytvářet nové objekty při vzniku události – ty by jen zbytečně zaplňovaly haldu (heap) a její plnění by vedlo i k pozastavování aplikace ve chvílích, kdy by se spouštěl správce paměti (garbage collector). Proto bývá obvykle hra naprogramovaná s využitím SDLJava plynulejší, než podobná aplikace naprogramovaná s využitím AWT či Swingu (nemluvě již o obecně vyšším výkonu SDLJava při provádění grafických operací).
Současná verze knihovny SDLJava pracuje s následujícími typy událostí:
# | Událost |
---|---|
1 | sdljava.event.SDLActiveEvent |
2 | sdljava.event.SDLExposeEvent |
3 | sdljava.event.SDLJoyAxisEvent |
4 | sdljava.event.SDLJoyBallEvent |
5 | sdljava.event.SDLJoyButtonEvent |
6 | sdljava.event.SDLJoyHatEvent |
7 | sdljava.event.SDLKeyboardEvent |
8 | sdljava.event.SDLMouseButtonEvent |
9 | sdljava.event.SDLMouseMotionEvent |
10 | sdljava.event.SDLQuitEvent |
11 | sdljava.event.SDLResizeEvent |
12 | sdljava.event.SDLSysWMEvent |
Princip zpracování jednotlivých typů událostí si postupně ukážeme na několika demonstračních příkladech.
6. Demonstrační příklad SDLTest28 – čtení událostí ve smyčce
V demonstračním příkladu pojmenovaném SDLTest28 je ukázán nejjednodušší typ smyčky pro zpracování událostí. Tato (nekonečná) smyčka je implementována v metodě eventLoop() a provádí pouze tři činnosti – čekání na příchod nové události, přečtení této události a následně výpis jména třídy, jejíž objekt reprezentuje právě zachycenou událost. Povšimněte si, že demonstrační příklad nelze jednoduše ukončit uzavřením jeho okna, protože v tomto případě se „pouze“ vytvoří událost typu SDLQuitEvent, na níž se však nijak nereaguje. Příklad tedy ukončíte například přes CTRL+C, zasláním signálu atd. Samotná smyčka pro zpracování událostí vypadá následovně:
/** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); System.out.println(event.getClass().getName()); } }

Obrázek 3: Ukázka výstupu demonstračního příkladu SDLTest28.
Úplný zdrojový kód demonstračního příkladu SDLTest28:
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.event.SDLEvent; import sdljava.video.SDLVideo; /** * Dvacaty osmy demonstracni priklad vyuzivajici knihovnu SDLjava. * * Cteni udalosti. * * @author Pavel Tisnovsky */ public class SDLTest28 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 320; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 240; /** * 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 void initVideo() throws SDLException { final long flags = SDLVideo.SDL_DOUBLEBUF; SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); System.out.println(event.getClass().getName()); } } /** * Spusteni osmeho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_VIDEO); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani initVideo(); // smycka pro zpracovani udalosti eventLoop(); } 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 SDLTest28.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 SDLTest28.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 SDLTest28
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% SDLTest28
7. Demonstrační příklad SDLTest29 – reakce na událost typu SDLQuitEvent
Chování předchozího demonstračního příkladu SDLTest28 bylo – politicky korektně řečeno – poněkud „nestandardní“ ;-), protože uživatelé očekávají, že se po zavření okna příslušná aplikace skutečně ukončí. Toho lze velmi snadno dosáhnout i při použití knihovny SDLJava, a to konkrétně takovým způsobem, že se správně zareaguje na událost typu SDLQuitEvent. Tato událost typicky vzniká právě při pokusu o uzavření okna aplikace, a to nezávisle na tom, na jakém operačním systému je aplikace spuštěna. Jeden z nejjednodušších způsobů reakce na událost typu SDLQuitEvent je ukončení běhu smyčky událostí:
/** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); System.out.println(event.getClass().getName()); // vyskok ze smycky pro zpracovani udalosti pri vyskytu // udalosti typu SDLQuitEvent if (event instanceof SDLQuitEvent) { return; } } }
Opět následuje výpis celého zdrojového kódu demonstračního příkladu SDLTest29:
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.event.SDLEvent; import sdljava.event.SDLQuitEvent; import sdljava.video.SDLVideo; /** * Dvacaty devaty demonstracni priklad vyuzivajici knihovnu SDLjava. * * Cteni udalosti a reakce na udalost typu SDLQuitEvent. * * @author Pavel Tisnovsky */ public class SDLTest29 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 320; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 240; /** * 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 void initVideo() throws SDLException { final long flags = SDLVideo.SDL_DOUBLEBUF; SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); System.out.println(event.getClass().getName()); // vyskok ze smycky pro zpracovani udalosti pri vyskytu // udalosti typu SDLQuitEvent if (event instanceof SDLQuitEvent) { return; } } } /** * Spusteni osmeho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_VIDEO); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani initVideo(); // smycka pro zpracovani udalosti eventLoop(); } 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 SDLTest29.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 SDLTest29.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 SDLTest29
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% SDLTest29
8. Demonstrační příklad SDLTest30 – čtení informací o stisknutých a puštěných klávesách
Kromě události typu SDLQuitEvent lze samozřejmě reagovat i na další typy událostí. V dnešním posledním demonstračním příkladu nazvaném SDLTest30 je ukázán základní způsob zpracování události typu SDLKeyboardEvent. Tato událost vznikne ve chvíli stlačení či naopak puštění nějaké klávesy – důležitý je zde právě fakt, že dokážeme snadno detekovat i okamžik puštění nějaké klávesy, což se hodí při programování her. Objekt typu SDLKeyboardEvent nese několik důležitých informací, především pak kód stisknuté/puštěné klávesy a stav této klávesy. Kódy kláves lze porovnávat s konstantami uloženými ve třídě SDLKey. V demonstračním příkladu je tímto způsobem reagováno na stisk klávesy ESC, která běh demonstračního příkladu ukončí:
/** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); // vyskok ze smycky pro zpracovani udalosti pri vyskytu // udalosti typu SDLQuitEvent if (event instanceof SDLQuitEvent) { return; } // stisk ci pusteni klavesy if (event instanceof SDLKeyboardEvent) { final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event; final int symbol = keyEvent.getSym(); final String state = keyEvent.getState() == SDLPressedState.PRESSED ? "pressed" : "release"; System.out.println("Keyboard event: symbol=" + symbol +" state=" + state); // ESC ukonci program if (symbol == SDLKey.SDLK_ESCAPE) { return; } } } }
Úplný zdrojový kód demonstračního příkladu SDLTest30 vypadá následovně:
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.event.SDLEvent; import sdljava.event.SDLKeyboardEvent; import sdljava.event.SDLKey; import sdljava.event.SDLQuitEvent; import sdljava.video.SDLVideo; import sdljava.x.swig.SDLPressedState; /** * Dvacaty devaty demonstracni priklad vyuzivajici knihovnu SDLjava. * * Cteni udalosti a reakce na stisk klaves. * * @author Pavel Tisnovsky */ public class SDLTest30 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 320; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 240; /** * 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 void initVideo() throws SDLException { final long flags = SDLVideo.SDL_DOUBLEBUF; SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); // vyskok ze smycky pro zpracovani udalosti pri vyskytu // udalosti typu SDLQuitEvent if (event instanceof SDLQuitEvent) { return; } // stisk ci pusteni klavesy if (event instanceof SDLKeyboardEvent) { final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event; final int symbol = keyEvent.getSym(); final String state = keyEvent.getState() == SDLPressedState.PRESSED ? "pressed" : "release"; System.out.println("Keyboard event: symbol=" + symbol +" state=" + state); // ESC ukonci program if (symbol == SDLKey.SDLK_ESCAPE) { return; } } } } /** * Spusteni osmeho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_VIDEO); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani initVideo(); // smycka pro zpracovani udalosti eventLoop(); } 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 SDLTest30.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 SDLTest30.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 SDLTest30
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% SDLTest30
9. Repositář se zdrojovými kódy všech pěti dnešních demonstračních příkladů
Všech pět dnes popsaných demonstračních příkladů bylo společně s podpůrnými skripty určenými pro jejich překlad a následné spuštění uloženo 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 sedmi 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:
10. 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