Hlavní navigace

Pohled pod kapotu JVM – složitější tělesa, textury a sprity v knihovně SDLJava

11. 2. 2014
Doba čtení: 29 minut

Sdílet

V dnešní části seriálu o jazyce Java i o virtuálním stroji Javy si řekneme, jak lze v knihovně SDLJava obejít funkce glBegin a glEnd z OpenGL 1 (které již nejsou v OpenGL 3.1 a ES oficiálně podporovány) pomocí polí vrcholů (vertex arrays). Seznámíme se také s třídou Sprite využitelnou nejenom ve hrách.

Obsah

1. Pohled pod kapotu JVM – složitější tělesa, textury a sprity v knihovně SDLJava

2. Pole vrcholů

3. Vytvoření pole vrcholů

4. ByteBuffer versus pole v Javě

5. Výběr prvků z pole/bufferu a přenos jednotlivých vrcholů na grafický akcelerátor

6. Demonstrační příklad SDLTest17 – použití metody glArrayElement()

7. Demonstrační příklad SDLTest18 – použití metody glDrawArrays()

8. Objekt typu Sprite v knihovně SDLJava

9. Demonstrační příklad SDLTest19 – texturování a objekt typu Sprite

10. Repositář se zdrojovými kódy všech tří dnešních demonstračních příkladů

11. Odkazy na Internetu

1. Pohled pod kapotu JVM – složitější tělesa, textury a sprity v knihovně SDLJava

V předchozí části tohoto seriálu jsme si řekli, že pomocí grafické knihovny OpenGL a SDLJava je možné vykreslovat pouze několik základních grafických prvků – grafických primitiv. Veškeré složitější tvary těles se musí složit z těchto grafických primitiv, což ve většině případů při zobrazování trojrozměrných scén znamená využití trojúhelníků a čtyřúhelníků. Kromě obecných vlastností těchto prvků je v některých případech zapotřebí zadávat i vlastnosti jednotlivých vrcholů. Mezi tyto vlastnosti, které se typicky nastavují uvnitř takzvaných „programových závorek“ glBegin()glEnd(), patří:

  • Pozice vrcholu (vertexu) v rovině či prostoru. Nastavuje se metodouGL.glVertex*(), přičemž lze zadat dvě souřadnice (rovina), tři souřadnice (prostor) nebo čtyři souřadnice (prostor+„váha“ vrcholu reprezentovaná čtvrtou souřadicí).
  • Barva vrcholu, která se nastavuje metodou GL.glColor*(). Barva plošky mezi vrcholy (stejně jako některé další parametry) může být dopočítána pomocí interpolace.
  • Index barvy vrcholu v barvové paletě, který se nastavuje metodouGL.glIndex*(). Barvové palety a indexované barvy byly do knihovny OpenGL zařazeny pro podporu vykreslování na starších grafických subsystémech, které nepodporovaly režim True-Color. V dnešní době však ztratily smysl (kromě diskutabilní animace pomocí změny jednotlivých barev) a přestávají být také v nových grafických kartách podporovány, proto se jimi dále nebudeme zabývat (od OpenGL 3.1 už ani tato vlastnost oficiálně není v základním režimu povolena, tuto vlastnost nemá smysl hledat ani v OpenGL ES 1.x/ES 2.x apod., což je možná ještě důležitější, především pro vývojáře aplikací pro tablety apod.).
  • Normálový vektor ve vrcholu, který se nastavuje metodouGL.glNormal*(). Normála (tj. vektor kolmý k povrchu) vrcholu je sice z matematického hlediska nesmysl, ale v počítačové grafice se normály rovin, které se ve vrcholech stýkají, sečítají a výsledek se používá například při výpočtech osvětlení.
  • Souřadnice do textury, která se nastavuje metodouGL.glTexCoord(). Tato souřadnice se používá při texturování, kterým se budeme podrobněji zabývat v následujících kapitolách.
  • Mapovací souřadnice zadávaná metodouGL.glEvalCoord*().
  • Jednorozměrný či dvourozměrný bod v síti (mesh), který se zadává metodou GL.glEvalPoint*().
  • Optické vlastnosti materiálu zadané metodouGL.glMaterial().
  • Vlastnosti hrany (tj. zda má být hrana viditelná či nikoliv) nastavované metodou GL.glEdgeFlag().

2. Pole vrcholů

Vlastnosti jednotlivých vrcholů se v nejjednodušším případě zadávají přímým voláním jednoduchých metod, například GL.glVertex*(), GL.glColor*(), GL.glNormal*()glGL.Material*(). Toto řešení je snadno pochopitelné i použitelné, jeho obrovskou nevýhodou však je, že pro vykreslení složitých prostorových scén by se muselo těchto funkcí volat několik tisíc i desítek tisíc (podle složitosti těchto scén, tj. počtu vrcholů).

Volání každé funkce s sebou nese poměrně značné množství práce pro procesor, zejména přesuny dat mezi registry procesoru, pamětí a zásobníkem a také skok do funkce a návrat z funkce (snížení účinnosti cache paměti z hlediska lokálnosti odkazů a přepínání mezi ringy), nemluvě již o nutnosti používat JNI při volání těchto nativních funkcí z Javy. Proto by bylo vhodné co nejvíce snížit množství volání funkcí nutných pro vykreslení dané scény. Existuje více možností vedoucích ke snížení počtu volaných funkcí, které se liší svou složitostí, vyjadřovací schopností (tj. které grafické efekty lze popř. naopak nelze vytvořit) a rychlostí vlastního vykreslení:

  1. První možností, která je pro použití nejjednodušší, je využití faktu, že se OpenGL chová jako stavový automat, tj. pokud zadáme nějakou vlastnost, zůstane tato vlastnost nastavena až do doby, než ji změníme.
  2. Druhou možností je použití těch grafických primitiv, u kterých se redukuje počet přenesených vrcholů. Jedná se o již popsané trsypruhy trojúhelníků a o pruh čtyřúhelníků (triangle fan, triangle strip, quad strip). Redukce přenesených vrcholů spočívá v tom, že vrcholy společné více hranám (a tím pádem i ploškám) jsou přeneseny pouze jednou.
  3. Třetí možností je použití display listů, kdy se příkazy nutné pro vytvoření tělesa uloží do display listu a ten se poté zavolá pomocí jediné funkce. Předností tohoto postupu je, že data uložená v display listu jsou v ideálním případě zapsána přímo do paměti grafického akcelerátoru a při každém vykreslení tedy není nutné tato data přenášet po sběrnici, což je v dnešní době (se současnými sběrnicemi a grafickými akcelerátory) nejvíce zpomalující operace při vykreslování trojrozměrných scén.
  4. Čtvrtou možností, kterou se dnes budeme podrobněji zabývat, je použití takzvaného pole vrcholů (vertex arrays), kdy jsou data pro jednotlivé vrcholy uložena ve vhodně organizovaném poli a následně je umožněno poslání dat vrcholů pomocí několika málo funkčních volání. Největší předností tohoto přístupu je, že se mezi jednotlivými snímky mohou měnit data jednotlivých vrcholů (barva, poloha apod.), což v případě display listů nebylo možné, protože by se při jakékoliv změně musel vytvořit nový display list.
  5. Předchozí možnost lze dále vylepšit použitím Vertex Buffer Object (VBO) typu GL_STATIC_DRAW, což jsou data ukládaná přímo do paměti grafického akcelerátoru bez možnosti je někdy měnit (což s sebou může přinášet jak výhody, tak i nevýhody).

Při vývoji nových aplikací je taktéž nutné mít na paměti, že v OpenGL verze 3.0 už je vykreslování s využitím „příkazových závorek“ glBeginglEnd označeno jako deprecated a od OpenGL 3.1 už nemusí být tyto vlastnosti v základní variantě OpenGL vůbec podporovány. Jedná se samozřejmě o reakci na směr vývoje moderních grafických akcelerátorů a GPU, kde se namísto toho používá funkcí glDrawArrays, glDrawArraysInstanced, glDrawElements atd.

3. Vytvoření pole vrcholů

Před prvním použitím pole vrcholů v programu je zapotřebí použití pole vrcholů povolit zavoláním metody GL.glEnableClientState(array), kde parametr array může podle potřeby nabývat několika hodnot:

  • GL.GL_COLOR_ARRAY – v poli je možné mít uloženy RGB barvy vrcholů (používá se v True-color RGB barevném režimu).
  • GL.GL_INDEX_ARRAY – v poli je možné mít uloženy indexové barvy vykreslování (používá se paletovém barevném režimu, již většinou nepodporováno).
  • GL.GL_EDGE_FLAG_ARRAY – v poli je možné mít uloženy příznaky hrany, tj. zda má být vykreslovaná hrana viditelná.
  • GL.GL_NORMAL_ARRAY – v poli je možné mít uloženy normálové vektory ve vrcholech.
  • GL.GL_TEXTURE_COORD_ARRAY – v poli je možné mít uloženy souřadnice do textury.
  • GL.GL_VERTEX_ARRAY – v poli je možné mít uloženy souřadnice vrcholů v rovině či prostoru.

Pokud některé z těchto polí nebudeme chtít použít, je možné zavolat metodu GL.glDisableClientState(array), kde parametr array nabývá stejných hodnot jako u předchozí funkce. Stav povolení či zakázání některého typu pole lze zjistit voláním metody GL.glIsEnabled().

4. ByteBuffer versus pole v Javě

Druhým krokem je vlastní vytvoření pole vrcholů. Toto pole se musí naplnit relevantními daty a poté předat knihovně OpenGL ukazatel na toto pole. To se v případě nativního rozhraní OpenGL provede příkazem gl*Pointer(), kde se za znak * doplní typ pole. To znamená, že podle typu uložených dat existují funkce:
glVertexPointer(),
glColorPointer(),
glIndexPointer(),
glNormalPointer(),
glTexCoordPointer() a
glEdgeFlagPointer().

V případě použití knihovny SDLJava však samozřejmě není možné specifikovat ukazatel na pole a dokonce pro uložení dat o jednotlivých vrcholech nelze použít javovská pole, a to z toho důvodu, že tato pole mohou být kdykoli v paměti přemístěna při spuštění správce paměti. Z tohoto důvodu používá knihovna SDLJava třídu java.nio.ByteBuffer, protože zde je při alokaci zaručeno, že se vytvořený buffer (interně pole) nebude přesouvat při zavolání GC. To znamená, že předchozí céčkové funkce gl*Pointer() se při použití knihovny SDLJava sice stále jmenují GL.gl*Pointer, ale posledním parametrem těchto metod je ve skutečnosti reference na ByteBuffer!

5. Výběr prvků z pole/bufferu a zobrazení jednotlivých vrcholů

Po povolení použití polí vrcholů a naplnění těchto polí je zapotřebí vhodným způsobem vybrat prvky z pole a vykreslit jednotlivé vrcholy. Je nutné si uvědomit, že pole zůstává uloženo na straně klienta (v případě PC v paměti procesoru) do té doby, dokud poprvé nepřistoupíme k jeho prvkům. Poté jsou pole přenesena na server (v případě PC na grafický akcelerátor, ale zde hodně záleží na použitém ovladači a velikosti volné paměti na grafickém akcelerátoru). Změníme-li později hodnoty v poli, musíme si vynutit zaslání nového pole na server.

Prvky pole lze vybrat několik různými způsoby:

  1. Po jednotlivých vrcholech metodou GL.glArrayElement(int i), která vybere data z i-tého prvku ze všech zapnutých polí. Zavolání této metody má stejný efekt jako volání metody GL.glVertex(), GL.glColor() atd. Tento způsob se jako jediný používá mezi příkazovými závorkami glBegin()glEnd() a tudíž už nemusí být v případě OpenGL 3.1 a vyšší vždy podporovaný.
  2. Zadáním seznamu několika vrcholů pomocí metodyGL.glDrawElements(mode, count, type, buffer). Tato metoda vybere count vrcholů ze všech zapnutých polí, přičemž posloupnost indexů vybíraných vrcholů je uložena v bufferu indices. Typ tohoto pole pak určuje parametr type, který může nabývat hodnot GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT nebo GL_UNSIGNED_INT. Parametr mode určuje, jaká geometrická primitiva mají být z vybíraných vrcholů konstruována (GL_TRIANGLES, GL_POLYGON atd., tedy stejné jako parametr funkce glBegin()).
  3. V novějších verzích OpenGL lze využít i podobnou funkciglDrawElementsInstanced díky níž lze jedno pole použít pro několik těles.
  4. Zadáním seznamu několika po sobě jdoucích vrcholů pomocí metodyGL.glDrawArrays(mode, first, count). Tato funkce vybere count vrcholů, které jsou uloženy v poli za sebou. Index prvního vrcholu je určen parametrem first.
  5. I pro glDrawArrays existuje v novějších verzích OpenGL alternativní funkce glDrawArraysInstanced použitelná pro vykreslení několika těles uložených v jednom poli.

6. Demonstrační příklad SDLTest17 – použití metody glArrayElement()

V dnešním prvním demonstračním příkladu nazvaném SDLTest17 je ukázán způsob vytvoření polí typu GL_VERTEX_ARRAYGL_COLOR_ARRAY a následné vykreslení dvou úseček s použitím metody glArrayElement(). Povšimněte si především způsobu alokace obou bufferů i metod, pomocí nichž se do objektu typu ByteBuffer mohou ukládat data jiného datového typu. Pro konstrukci bufferu je nutné použít metodu ByteBuffer.allocateDirect(velikost) s následným voláním metody ByteBuffer.order(ByteOrder­.nativeOrder(), díky níž je zajištěno uložení bajtů v bufferu takovým způsobem, který je na použité platformě nativní (little endian či big endian). Pokud by se tato metoda nezavolala, ukládaly by se bajty hodnot typu short/int/float/long/double v opačném pořadí, než je na platformě x86 očekáváno a vykreslení scény by nebylo korektní!

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;
 
 
 
/**
 * Sedmnacty demonstracni priklad vyuzivajici knihovnu SDLjava.
 *
 * Priklad vyuziti metody Gl.glArrayElement() pro vykreslovani
 * komplikovanejsich objektu a teles.
 *
 * @author Pavel Tisnovsky
 */
public class SDLTest17 {
 
    /**
     * 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;
 
    /**
     * Buffer obsahujici vrcholy usecek.
     */
    private static ByteBuffer verticesBuffer = null;
 
    /**
     * Buffer obsahujici barvy vrcholu usecek.
     */
    private static ByteBuffer colorsBuffer = null;
 
    /* Inicializace bufferu */
    static {
        /* 8 souradnic * 4 bajtu/int = 32 bajtu */
        /* je nutne zachovat nativni usporadani bajtu ve slovech! */
        verticesBuffer = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
        verticesBuffer.putInt(10);  verticesBuffer.putInt(10);
        verticesBuffer.putInt(190); verticesBuffer.putInt(190);
        verticesBuffer.putInt(10);  verticesBuffer.putInt(190);
        verticesBuffer.putInt(190); verticesBuffer.putInt(10);
        verticesBuffer.flip();
 
        /* 12 barvovych slozek * 4 bajtu/float = 48 bajtu */
        /* je nutne zachovat nativni usporadani bajtu ve slovech! */
        colorsBuffer = ByteBuffer.allocateDirect(48).order(ByteOrder.nativeOrder());
        colorsBuffer.putFloat(0.0f); colorsBuffer.putFloat(0.0f); colorsBuffer.putFloat(1.0f);
        colorsBuffer.putFloat(1.0f); colorsBuffer.putFloat(0.0f); colorsBuffer.putFloat(1.0f);
        colorsBuffer.putFloat(1.0f); colorsBuffer.putFloat(1.0f); colorsBuffer.putFloat(0.0f);
        colorsBuffer.putFloat(0.0f); colorsBuffer.putFloat(1.0f); colorsBuffer.putFloat(1.0f);
        colorsBuffer.flip();
    }
 
    /**
     * 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, 0, height, -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);
 
        // 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) {
 
        // vymazani framebufferu
        gl.glClear(gl.GL_COLOR_BUFFER_BIT);
 
        gl.glEnable(gl.GL_LINE_SMOOTH);                      // povoleni antialiasingu usecek
        gl.glEnableClientState(gl.GL_VERTEX_ARRAY);          // povoleni pouziti pole vrcholu
        gl.glEnableClientState(gl.GL_COLOR_ARRAY);           // povoleni pouziti pole barev
 
        gl.glVertexPointer(2, gl.GL_INT, 0, verticesBuffer); // naplneni pole vrcholu
        gl.glColorPointer(3, gl.GL_FLOAT, 0, colorsBuffer);  // naplneni pole barev
 
        gl.glBegin(gl.GL_LINES);
            for (int i=0; i<4; i++) {                        // vykreslit vsechny vrcholy
                gl.glArrayElement(i);                        // (vcetne zmeny barvy)
            }
        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);
 
            // vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL
            drawScene(gl);
 
            // 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 SDLTest17.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 SDLTest17.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 SDLTest17

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% SDLTest17

Obrázek 1: Scéna vykreslená po spuštění demonstračního příkladu SDLTest17.

7. Demonstrační příklad SDLTest18 – použití metody glDrawArrays()

Demonstrační příklad SDLTest18 se v mnoha ohledech podobá předchozímu demonstračnímu příkladu, ovšem namísto volání metody GL.glArrayElement() se zde používá mnohem efektivnějšího způsobu – metody GL.glDrawArrays(), která jediným zavoláním dokáže vykreslit i složitou scénu. Této metodě se předávají tři parametry – typ vykreslovaných grafických primitiv (body, úsečky, trojúhelníky …), počáteční index v polích, od kterého se má zahájit čtení (0=první prvky v polích) a konečně počet prvků polí nutných pro získání všech dat pro vykreslované grafické primitivum (konstanta 4 znamená, že se přečtou souřadnice a barvy čtyř vrcholů, z nichž se vytvoří dvě úsečky, stejně, jako kdyby se čtyřikrát zavolala metoda glVertex*):

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;
 
 
 
/**
 * Osmnacty demonstracni priklad vyuzivajici knihovnu SDLjava.
 *
 * Priklad vyuziti metody Gl.glDrawArrays() pro vykreslovani
 * komplikovanejsich objektu a teles.
 *
 * @author Pavel Tisnovsky
 */
public class SDLTest18 {
 
    /**
     * 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;
 
    /**
     * Buffer obsahujici vrcholy usecek.
     */
    private static ByteBuffer verticesBuffer = null;
 
    /**
     * Buffer obsahujici barvy vrcholu usecek.
     */
    private static ByteBuffer colorsBuffer = null;
 
    /* Inicializace bufferu */
    static {
        /* 8 souradnic * 4 bajtu/int = 32 bajtu */
        /* je nutne zachovat nativni usporadani bajtu ve slovech! */
        verticesBuffer = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
        verticesBuffer.putInt(10);  verticesBuffer.putInt(10);
        verticesBuffer.putInt(190); verticesBuffer.putInt(190);
        verticesBuffer.putInt(10);  verticesBuffer.putInt(190);
        verticesBuffer.putInt(190); verticesBuffer.putInt(10);
        verticesBuffer.flip();
 
        /* 12 barvovych slozek * 4 bajtu/float = 48 bajtu */
        /* je nutne zachovat nativni usporadani bajtu ve slovech! */
        colorsBuffer = ByteBuffer.allocateDirect(48).order(ByteOrder.nativeOrder());
        colorsBuffer.putFloat(0.0f); colorsBuffer.putFloat(0.0f); colorsBuffer.putFloat(1.0f);
        colorsBuffer.putFloat(1.0f); colorsBuffer.putFloat(0.0f); colorsBuffer.putFloat(1.0f);
        colorsBuffer.putFloat(1.0f); colorsBuffer.putFloat(1.0f); colorsBuffer.putFloat(0.0f);
        colorsBuffer.putFloat(0.0f); colorsBuffer.putFloat(1.0f); colorsBuffer.putFloat(1.0f);
        colorsBuffer.flip();
    }
 
    /**
     * 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, 0, height, -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);
 
        // 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) {
 
        // vymazani framebufferu
        gl.glClear(gl.GL_COLOR_BUFFER_BIT);
 
        gl.glEnable(gl.GL_LINE_SMOOTH);                      // povoleni antialiasingu usecek
        gl.glEnableClientState(gl.GL_VERTEX_ARRAY);          // povoleni pouziti pole vrcholu
        gl.glEnableClientState(gl.GL_COLOR_ARRAY);           // povoleni pouziti pole barev
 
        gl.glVertexPointer(2, gl.GL_INT, 0, verticesBuffer); // naplneni pole vrcholu
        gl.glColorPointer(3, gl.GL_FLOAT, 0, colorsBuffer);  // naplneni pole barev
 
        gl.glDrawArrays(gl.GL_LINES, 0, 4);                  // vykreslit vsechny vrcholy
                                                             // (vcetne zmeny barvy)
 
        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);
 
            // vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL
            drawScene(gl);
 
            // 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 SDLTest18.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 SDLTest18.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 SDLTest18

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% SDLTest18

Obrázek 1: Scéna vykreslená po spuštění demonstračního příkladu SDLTest18.

8. Objekt typu Sprite v knihovně SDLJava

Knihovna OpenGL a tím pádem i SDLJava samozřejmě umožňuje nanášet na vykreslované plochy rastrové textury. Velkou výhodou rastrových textur je jejich snadná implementace ve vykreslovacím řetězci. Jednoduché grafické akcelerátory používané v minulosti řešily texturování takovým způsobem, že se do jejich vykreslovacího řetězce přidala vyrovnávací paměť pro textury a několik interpolátorů, pomocí kterých se zajistil přístup do texturovací paměti. Dnešní moderní grafické akcelerátory a GPU jdou mnohem dál: textury je možné komprimovat, jsou podporovány mipmapy (textury ve více rozlišeních), antialiasing, multitextury apod. Texturovací jednotka však stále patří k těm částem vizuálního systému, která má velmi dobrý poměr složitost/vizuální efekt.

Vzhledem k tomu, že se knihovna SDL a tím pádem i SDLJava často používá pro tvorbu počítačových her (ať již s 2D či 3D scénami), byla do balíčku org.gljava.opengl přidána třída nazvaná Sprite, kterou lze využít pro načtení bitmapy z externího souboru a následné vykreslení této bitmapy jednoduchou operací Sprite.draw(GL, x, y), kde GL je kontext OpenGL a x a y jsou pozice spritu ve scéně. Samotná knihovna SDLJava zajistí převod spritu na formát textury a vykreslení objektu (čtverce či obdélníku) pokrytého touto texturou, což je mnohem jednodušší, než běžný postup při texturování v OpenGL.

Mezi metody, které třída Sprite programátorům nabízí, patří:

# Metoda Význam
1 Sprite(Texture t) vytvoření spritu z textury (bude popsáno příště)
2 Sprite(GL gl, java.net.URL url) načtení spritu z rastrového obrázku
3 Sprite(GL gl, java.lang.String texturePath) načtení spritu z rastrového obrázku
4 draw(GL gl, float x, float y) vykreslení spritu
5 getWidth() získání šířky spritu v pixelech
6 getHeight() získání výšky spritu v pixelech

Pokud je zapotřebí sprite při vykreslování natočit, lze tuto operaci provést jen nepřímo a to natočením celého souřadného systému. Posléze je většinou nutné obnovit původní transformační matici naprosto stejným způsobem, jaký se provádí například při vykreslení natočeného či zvětšeného/zmenšeného tělesa.

9. Demonstrační příklad SDLTest19 – texturování a objekt typu Sprite

V dnešním posledním demonstračním příkladu SDLTest19 je ukázán způsob načtení spritu z rastrového obrázku (opět je použita již několikrát zobrazená obrazovka hry Xscorch) s následným vykreslením tohoto spritu. Nejprve je sprite vykreslen v takovém souřadném systému, že jsou jeho hrany rovnoběžné s hranami okna, podruhé je sprite otočen o 45 stupňů, přesněji řečeno souřadný systém je před vykreslením spritu otočen o tuto hodnotu (což je ve výsledku to samé):

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.Sprite;
 
 
 
/**
 * Devatenacty demonstracni priklad vyuzivajici knihovnu SDLjava.
 *
 * Texturovani a objekt typu Sprite.
 *
 * @author Pavel Tisnovsky
 */
public class SDLTest19 {
 
    /**
     * 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);
 
        // 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, Sprite sprite) {
 
        // vymazani framebufferu
        gl.glClear(gl.GL_COLOR_BUFFER_BIT);
 
        // vykresleni spritu
        sprite.draw(gl, 200, 400);
 
        // otoceni souradneho systemu
        gl.glMatrixMode(gl.GL_MODELVIEW);
        gl.glRotatef(45.0f, 0.0f, 0.0f, 1.0f);
 
        // vykresleni druheho spritu
        sprite.draw(gl, 200, 0);
 
        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 spritu z rastroveho obrazku
            Sprite sprite = new Sprite(gl, "xscorch.bmp");
 
            // vykresleni velmi jednoduche sceny s vyuzitim funkci OpenGL
            drawScene(gl, sprite);
 
            // 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 SDLTest19.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 SDLTest19.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 SDLTest19

Dávkový soubor pro spuštění na Windows:

UX DAy - tip 2

set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib
 
java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest19

Obrázek 1: Scéna vykreslená po spuštění demonstračního příkladu SDLTest19.

10. 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ženo do Mercurial repositáře dostupného na adrese http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/. Podobně jako tomu bylo i v předchozích čtyřech 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:

# Zdrojový soubor/skript Umístění souboru v repositáři
1 SDLTest17.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest17/SDLTest17.ja­va
2 SDLTest17_compile.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest17/SDLTest17_com­pile.sh
3 SDLTest17_compile_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest17/SDLTest17_com­pile_sys.sh
4 SDLTest17_run.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest17/SDLTest17_run­.sh
5 SDLTest17_run_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest17/SDLTest17_run_sys­.sh
6 SDLTest17_compile.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest17/SDLTest17_com­pile.bat
7 SDLTest17_run.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest17/SDLTest17_run­.bat
     
8 SDLTest18.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest18/SDLTest18.ja­va
9 SDLTest18_compile.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest18/SDLTest18_com­pile.sh
10 SDLTest18_compile_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest18/SDLTest18_com­pile_sys.sh
11 SDLTest18_run.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest18/SDLTest18_run­.sh
12 SDLTest18_run_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest18/SDLTest18_run_sys­.sh
13 SDLTest18_compile.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest18/SDLTest18_com­pile.bat
14 SDLTest18_run.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest18/SDLTest18_run­.bat
     
15 SDLTest19.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest19/SDLTest19.ja­va
16 SDLTest19_compile.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest19/SDLTest19_com­pile.sh
17 SDLTest19_compile_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest19/SDLTest19_com­pile_sys.sh
18 SDLTest19_run.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest19/SDLTest19_run­.sh
19 SDLTest19_run_sys.sh http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest19/SDLTest19_run_sys­.sh
20 SDLTest19_compile.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest19/SDLTest19_com­pile.bat
21 SDLTest19_run.bat http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/d9d2ef329fbd/sdlja­va/SDLTest19/SDLTest19_run­.bat

11. Odkazy na Internetu

  1. glDrawArrays
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawArrays­.xml
  2. glDrawElements
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawElemen­ts.xml
  3. glDrawArraysInstanced
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawArraysIn­stanced.xml
  4. glDrawElementsInstanced
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawElemen­tsInstanced.xml
  5. Root.cz: Seriál Grafická knihovna OpenGL
    http://www.root.cz/serialy/graficka-knihovna-opengl/
  6. 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/
  7. Best Practices for Working with Vertex Data
    https://developer.apple.com/li­brary/ios/documentation/3ddra­wing/conceptual/opengles_pro­grammingguide/Techniquesfor­WorkingwithVertexData/Techni­quesforWorkingwithVertexDa­ta.html
  8. SDL 1.2 Documentation: SDL_Surface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsurface.html
  9. SDL 1.2 Documentation: SDL_PixelFormat
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlpixelformat.html
  10. SDL 1.2 Documentation: SDL_LockSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdllocksurface.html
  11. SDL 1.2 Documentation: SDL_UnlockSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlunlocksurface.html
  12. SDL 1.2 Documentation: SDL_LoadBMP
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlloadbmp.html
  13. SDL 1.2 Documentation: SDL_SaveBMP
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsavebmp.html
  14. SDL 1.2 Documentation: SDL_BlitSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlblitsurface.html
  15. SDL 1.2 Documentation: SDL_VideoInfo
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlvideoinfo.html
  16. SDL 1.2 Documentation: SDL_GetVideoInfo
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlgetvideoinfo.html
  17. Class BufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/i­mage/BufferStrategy.html
  18. Class Graphics
    http://docs.oracle.com/ja­vase/1.5.0/docs/api/java/aw­t/Graphics.html
  19. Double Buffering and Page Flipping
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/doublebuf.html
  20. BufferStrategy and BufferCapabilities
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/bufferstrategy.html
  21. Java:Tutorials:Double Buffering
    http://content.gpwiki.org/in­dex.php/Java:Tutorials:Dou­ble_Buffering
  22. Double buffer in standard Java AWT
    http://www.codeproject.com/Ar­ticles/2136/Double-buffer-in-standard-Java-AWT
  23. Java 2D: Hardware Accelerating – Part 1 – Volatile Images
    http://www.javalobby.org/fo­rums/thread.jspa?threadID=16840&tstar­t=0
  24. Java 2D: Hardware Accelerating – Part 2 – Buffer Strategies
    http://www.javalobby.org/ja­va/forums/t16867.html
  25. How does paintComponent work?
    http://stackoverflow.com/qu­estions/15544549/how-does-paintcomponent-work
  26. A Swing Architecture Overview
    http://www.oracle.com/technet­work/java/architecture-142923.html
  27. Class javax.swing.JComponent
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html
  28. Class java.awt.Component
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.html
  29. Class java.awt.Component.BltBufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.BltBufferStrategy.html
  30. Class java.awt.Component.FlipBufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.FlipBufferStrategy­.html
  31. Metoda java.awt.Component.isDoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.html#isDoubleBuffe­red()
  32. Metoda javax.swing.JComponent.is­DoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html#isDouble­Buffered()
  33. Metoda javax.swing.JComponent.set­DoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html#setDouble­Buffered(boolean)
  34. Javadoc – třída GraphicsDevice
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsDevice.html
  35. Javadoc – třída GraphicsEnvironment
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsEnvironment.html
  36. Javadoc – třída GraphicsConfiguration
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsConfiguration.html
  37. Javadoc – třída DisplayMode
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Dis­playMode.html
  38. Lesson: Full-Screen Exclusive Mode API
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/
  39. Full-Screen Exclusive Mode
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/exclusivemode.html
  40. Display Mode
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/displaymode.html
  41. Using the Full-Screen Exclusive Mode API in Java
    http://www.developer.com/ja­va/other/article.php/3609776/U­sing-the-Full-Screen-Exclusive-Mode-API-in-Java.htm
  42. Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
    http://www.mobilefish.com/tu­torials/java/java_quickgu­ide_jvm_instruction_set.html
  43. The JVM Instruction Set
    http://mpdeboer.home.xs4a­ll.nl/scriptie/node14.html
  44. MultiMedia eXtensions
    http://softpixel.com/~cwrig­ht/programming/simd/mmx.phpi
  45. SSE (Streaming SIMD Extentions)
    http://www.songho.ca/misc/sse/sse­.html
  46. Timothy A. Chagnon: SSE and SSE2
    http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf
  47. Intel corporation: Extending the Worldr's Most Popular Processor Architecture
    http://download.intel.com/techno­logy/architecture/new-instructions-paper.pdf
  48. SIMD architectures:
    http://arstechnica.com/ol­d/content/2000/03/simd.ar­s/
  49. GC safe-point (or safepoint) and safe-region
    http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html
  50. Safepoints in HotSpot JVM
    http://blog.ragozin.info/2012/10/sa­fepoints-in-hotspot-jvm.html
  51. Java theory and practice: Synchronization optimizations in Mustang
    http://www.ibm.com/develo­perworks/java/library/j-jtp10185/
  52. How to build hsdis
    http://hg.openjdk.java.net/jdk7/hot­spot/hotspot/file/tip/src/sha­re/tools/hsdis/README
  53. Java SE 6 Performance White Paper
    http://www.oracle.com/technet­work/java/6-performance-137236.html
  54. Lukas Stadler's Blog
    http://classparser.blogspot­.cz/2010/03/hsdis-i386dll.html
  55. How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
    http://dropzone.nfshost.com/hsdis.htm
  56. PrintAssembly
    https://wikis.oracle.com/dis­play/HotSpotInternals/Prin­tAssembly
  57. The Java Virtual Machine Specification: 3.14. Synchronization
    http://docs.oracle.com/ja­vase/specs/jvms/se7/html/jvms-3.html#jvms-3.14
  58. The Java Virtual Machine Specification: 8.3.1.4. volatile Fields
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-8.html#jls-8.3.1.4
  59. The Java Virtual Machine Specification: 17.4. Memory Model
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-17.html#jls-17.4
  60. The Java Virtual Machine Specification: 17.7. Non-atomic Treatment of double and long
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-17.html#jls-17.7
  61. Open Source ByteCode Libraries in Java
    http://java-source.net/open-source/bytecode-libraries
  62. ASM Home page
    http://asm.ow2.org/
  63. Seznam nástrojů využívajících projekt ASM
    http://asm.ow2.org/users.html
  64. ObjectWeb ASM (Wikipedia)
    http://en.wikipedia.org/wi­ki/ObjectWeb_ASM
  65. Java Bytecode BCEL vs ASM
    http://james.onegoodcooki­e.com/2005/10/26/java-bytecode-bcel-vs-asm/
  66. BCEL Home page
    http://commons.apache.org/bcel/
  67. Byte Code Engineering Library (před verzí 5.0)
    http://bcel.sourceforge.net/
  68. Byte Code Engineering Library (verze >= 5.0)
    http://commons.apache.org/pro­per/commons-bcel/
  69. BCEL Manual
    http://commons.apache.org/bcel/ma­nual.html
  70. Byte Code Engineering Library (Wikipedia)
    http://en.wikipedia.org/wiki/BCEL
  71. BCEL Tutorial
    http://www.smfsupport.com/sup­port/java/bcel-tutorial!/
  72. Bytecode Engineering
    http://book.chinaunix.net/spe­cial/ebook/Core_Java2_Volu­me2AF/0131118269/ch13lev1sec6­.html
  73. Bytecode Outline plugin for Eclipse (screenshoty + info)
    http://asm.ow2.org/eclipse/index.html
  74. Javassist
    http://www.jboss.org/javassist/
  75. Byteman
    http://www.jboss.org/byteman
  76. Java programming dynamics, Part 7: Bytecode engineering with BCEL
    http://www.ibm.com/develo­perworks/java/library/j-dyn0414/
  77. The JavaTM Virtual Machine Specification, Second Edition
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/VMSpec­TOC.doc.html
  78. The class File Format
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/Clas­sFile.doc.html
  79. javap – The Java Class File Disassembler
    http://docs.oracle.com/ja­vase/1.4.2/docs/tooldocs/win­dows/javap.html
  80. javap-java-1.6.0-openjdk(1) – Linux man page
    http://linux.die.net/man/1/javap-java-1.6.0-openjdk
  81. Using javap
    http://www.idevelopment.in­fo/data/Programming/java/mis­cellaneous_java/Using_javap­.html
  82. Examine class files with the javap command
    http://www.techrepublic.com/ar­ticle/examine-class-files-with-the-javap-command/5815354
  83. aspectj (Eclipse)
    http://www.eclipse.org/aspectj/
  84. Aspect-oriented programming (Wikipedia)
    http://en.wikipedia.org/wi­ki/Aspect_oriented_program­ming
  85. AspectJ (Wikipedia)
    http://en.wikipedia.org/wiki/AspectJ
  86. EMMA: a free Java code coverage tool
    http://emma.sourceforge.net/
  87. Cobertura
    http://cobertura.sourceforge.net/
  88. jclasslib bytecode viewer
    http://www.ej-technologies.com/products/jclas­slib/overview.html

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