Tutorial #07: Images

In diesem Tutorial werden Grafiken als texturierte Graph::PlaneGeometry-Objekte gezeichnet. Dabei ist zu beachten, dass die Breite und Höhe der Textur eine Zahl aus der Reihe 2^n sein muss (Power of 2). Gültige Werte sind z.B. 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 etc.

Version 1: 2D-Textur

Für unser Beispiel erzeugen wir eine Grafik mit dem Namen gfx_smiley.png und speichern diese im Unterordner gfx ab. Die Grafik wird in der Datei package.xml bekannt gemacht:

    <Resource id="gfx_smiley" fileName="gfx/gfx_smiley.png"/>

Für das Zeichnen der Grafik benötigen wir ein geignetes Material, bei dem die erste Textur-Einheit (Unit 0) aktiviert ist. Dieses Material erstellen wir in der Datei graph_materials.xml. Mit textureUnit0Enabled wird die Textur-Einheit 0 aktiviert und die Angabe von blendMode="ALPHA" erlaubt transparente Bereiche beim Zeichnen der Grafik.

<?xml version="1.0"?>
<Graph>
    <Namespace id="material" activeAndVisible="no">
        
        <FixedProgram
            id="prg_color_texture"
            textureUnit0Enabled="yes"
        />
        
        <Material
            id="mat_alpha_color_texture"
            programId="prg_color_texture"
            visibleFaces="FRONT_AND_BACK"
            blendMode="ALPHA"
            depthBufferMode="NONE"
        />

Zusätzlich erzeugen wir einen Graph::FlatTexture-Knoten, der die Grafikressource als Graphenknoten instanziert. Das Attribut pixelFormat definiert das Format der Grafik im Speicher. Das Pixelformat der Grafikdatei kann dabei durchaus ein anderes sein.

Mit dem Attribut useMipMaps kann die automatische Mip-Map-Generierung aktiviert werden. Dabei wird beim Laden der Grafik eine Mip-Map-Bildpyramide erzeugt. Ein Aktivieren hat daher höhere Ladezeiten und einen um 50% höheren Speicherbedarf zur Folge. Für 2D Anwendungen wird Mip-Mapping normalerweise eher selten benötigt, weshalb wir es auch für dieses Beispiel deaktivieren.

        <FlatTexture
            id="texture_smiley"
            imageResourceId="package_main:gfx_smiley"
            pixelFormat="R8_G8_B8_A8"
            useMipMaps="no"
        />
        
    </Namespace>
</Graph>

In der Datei graph_main.xml erzeugen wir eine Instanz dieser Objekte und aktivieren Sie für die folgenden Zeichenoperationen mit MaterialState bzw. TextureState.

<?xml version="1.0" ?>

<Graph>
    
    <Instance graphResourceId="package_main:graph_mat"/>
    <Instance graphResourceId="package_main:graph_camera"/>
    
    <MaterialState materialId="material/mat_alpha_color_texture"/>
    
    <TextureState textureId="material/texture_smiley"/>
    
    <PlaneGeometry
        id="plane"
        scaleFactorX="128" scaleFactorY="128"
    />
    
</Graph>

Als Ergebnis erhalten wir ein texturiertes PlaneGeometry-Objekt:

tut0107_v1.png
V1-Ausgabefenster

Version 2: Position und Größenänderung

Die Textur wird immer in das Objekt eingepasst. Je nach Größe und Seitenverhältnis des Objekts, wird die Textur entsprechend skaliert und/oder verzerrt (siehe Screenshot unten).

Mit den Attributen texCoordX1, texCoordX2, texCoordY1 und texCoordY2 kann ein Ausschnitt aus der Textur ausgewählt werden (Screenshot unten).

    <PlaneGeometry
        id="plane7"
        scaleFactorX="64" scaleFactorY="128"
        texCoordX1="0.0" texCoordX2="0.5" texCoordY1="0.0" texCoordY2="1.0"
        posX="150" posY="0"
    />
    
    <PlaneGeometry
        id="plane8"
        scaleFactorX="128" scaleFactorY="64"
        texCoordX1="0.0" texCoordX2="1.0" texCoordY1="0.0" texCoordY2="0.5"
        posX="-150" posY="0"
    />
tut0107_v2.png
Ausgabefenster mit skalierten und beschnittenen Texturen

Wenn durch die Position des Geometrieobjekts die einzelnen Pixel der Texturgrafik genau zwischen die Pixel der Display-Surface zu liegen kommen, erscheint das Bild durch die Interpolation unscharf (siehe unterste Reihe im Bild oben).

Um diese Unschärfe zu verhindern, müssen Grafiken mit einer geradzahligen Pixellänge auf einer ganzzahligen Position platziert werden. Grafiken mit ungeradzahliger Länge müssen genau zwischen zwei ganzzahligen Positionen platziert werden.

tut0107_pixel_interpolation.png
Pixel-Interpolation

Version 3: Farbige Textur

Wenn coloringEnabled und textureUnit0Enabled eingeschaltet sind, ergibt sich die Zeichenfarbe durch Multiplikation der beiden Farbparameter. Das kann zum Beispiel für Fade-In/Fade-Out Effekte (Alphakanal) oder zum Einfärben von Texturen verwendet werden.

        <FixedProgram
            id="prg_color_texture"
            textureUnit0Enabled="yes"
            coloringEnabled="yes"
        />

Zur besseren Veranschaulichung erstellen wir verschiedene Materialknoten und zeichnen damit jeweils zwei überlappende PlaneGeometry-Objekte. Die Parameter für Kamera, Licht, Textur und Farbe sind für alle Objekte gleich. Die Reihung erfolgt analog dem Lesefluss von links nach rechts und von oben nach unten.

        <FixedProgram
            id="prg_white"
        />
        <Material
            id="mat_white"
            programId="prg_white"
        />
        
        <FixedProgram
            id="prg_color"
            coloringEnabled="yes"
        />
        <Material
            id="mat_color"
            programId="prg_color"
        />

Die ersten beiden Objekte werden mit den Materialen mat_white und mat_color gezeichnet. Obwohl ein Texturparameter gesetzt ist, wird dieser nicht gezeichnet, da textureUnit0Enabled nicht aktiviert wurde.

        <FixedProgram
            id="prg_texture"
            textureUnit0Enabled="yes"
        />
        <Material
            id="mat_texture"
            programId="prg_texture"
            visibleFaces="FRONT_AND_BACK"
            blendMode="NONE"
            depthBufferMode="NONE"
        />
        <Material
            id="mat_alpha_texture"
            programId="prg_texture"
            visibleFaces="FRONT_AND_BACK"
            blendMode="ALPHA"
            depthBufferMode="NONE"
        />
        
        <FixedProgram
            id="prg_color_texture"
            textureUnit0Enabled="yes"
            coloringEnabled="yes"
        />
        <Material
            id="mat_color_texture"
            programId="prg_color_texture"
            visibleFaces="FRONT_AND_BACK"
            blendMode="NONE"
            depthBufferMode="NONE"
        />
        <Material
            id="mat_alpha_color_texture"
            programId="prg_color_texture"
            visibleFaces="FRONT_AND_BACK"
            blendMode="ALPHA"
            depthBufferMode="NONE"
        />

Bei den nächsten vier Objekten wurde die Textur-Einheit 0 aktiviert. Die Materialien unterscheiden sich durch unterschiedliche Werte für die Attribute coloringEnabled und blendMode. Nur wenn der blendMode auf "ALHA" gesetzt ist, wird der Alphakanal (Transparenz) beim Zeichnen berücksichtigt. Der Farbparameter hat einen Alpha-Wert von 0.5, weshalb das vierte Objekt halbdurchsichtig gezeichnet wird.

        <FixedProgram
            id="prg_texture_light"
            textureUnit0Enabled="yes"
            coloringEnabled="no"
            lightingEnabled="yes"
        />
        <Material
            id="mat_texture_light"
            programId="prg_texture_light"
            visibleFaces="FRONT_AND_BACK"
            blendMode="ALPHA"
            depthBufferMode="NONE"
        />
        
        <FixedProgram
            id="prg_color_texture_light"
            textureUnit0Enabled="yes"
            coloringEnabled="yes"
            lightingEnabled="yes"
        />
        <Material
            id="mat_color_light"
            programId="prg_color_texture_light"
            visibleFaces="FRONT_AND_BACK"
            blendMode="NONE"
            depthBufferMode="NONE"
        />
        <Material
            id="mat_alpha_color_texture_light"
            programId="prg_color_texture_light"
            visibleFaces="FRONT_AND_BACK"
            blendMode="ALPHA"
            depthBufferMode="NONE"
        />

Bei den letzten drei Objekten wurde zusätzlich das Attribut lightingEnabled auf "yes" gesetzt. Dadurch ergibt sich mit der passenden Lichtquelle ein einfacher Beleuchtungseffekt.

Zu beachten
Achtung: Für eine korrekte Beleuchtungsberechnung muss bei den entsprechenden PlaneGeometry-Objekten auch das Attribut hasNormal auf "yes" gesetzt werden. Das setzten des Attributs bewirkt, dass für diese Geometrie-Objekte auch die für die Beleuchtungsberechnung notwendigen Normalvektoren berechnet werden.
  <MaterialState materialId="material/mat_texture_light"/>
  <PlaneGeometry id="plane6"
    hasNormal="yes"
    scaleFactorX="128" scaleFactorY="128"
    posX="-150" posY="-150"
  />
  <PlaneGeometry id="plane6a"
    hasNormal="yes"
    scaleFactorX="128" scaleFactorY="128"
    posX="-145" posY="-145" depthOrder="1"
  />
tut0107_v3.png
V3-Ausgabefenster


Copyright © 2011-2018 Spraylight GmbH.