Tutorial Alphamasking

Aus DGL Wiki
Wechseln zu: Navigation, Suche

Alphamasking

Einleitung

In diesem Tutorial geht es um die Nutzung des Alphakanals einer Textur. Wie Sie wissen, besteht ein Bild (bzw. eine Textur) aus den drei Komponenten Rot, Grün und Blau. In OpenGL gibt es, den richtigen Modus vorausgesetzt (GL_RGBA), noch eine weitere Komponente, nämlich den Alphakanal.

Dieser kann genutzt werden, um nicht erwünschte Pixel einer Textur auszublenden. Viele Spiele nutzen das Alphablending, um Bäume oder Ähnliches darzustellen. Durch die Nutzung dieser Methode wird die Anzahl der zu zeichnenden Dreiecke stark verringert, da für einen Baum meist 2 Quads (also 4 Dreiecke) ausreichend sind. Ein gutes Beispiel hierfür (auch wenn die in diesem Spiel genutzte Methode, Bäume zu zeichnen nicht die Beste ist) ist Collin McRae 2.0 von Codemasters.


Schritt 1 - Den Alphakanal erstellen

Um eine Textur mit einem Alphakanal zu versehen, gibt es zwei Methoden. Zum Einen kann man diesen direkt in das Bild integrieren. Dies geht jedoch nicht mit jedem Bildbearbeitungsprogramm und setzt ein Bildformat voraus, das die Speicherung des Alphakanals unterstützt, wie dies z.B. bei TGA und PNG der Fall ist.

Die zweite Methode ist etwas einfacher. Neben der Basistextur erstellt man eine zweite Textur in der der Alphakanal gespeichert ist. Weisse Pixel werden gezeichnet, während die schwarzen Pixel durch das Alphatesting weggelassen werden. Im Falle des Demoprogrammes sehen die Texturen folgendermaßen aus:


Tutorial Alphamasking alphablend03.jpg Tutorial Alphamasking alphablend02.jpg
Basistextur Alphatextur


Schritt 2 - Den Alphakanal laden

Um die Sache zu erleichtern, wird auch in diesem Tutorial die GLBmp-Unit (http://delphigl.cfxweb.net) genutzt. Die von mir leicht modifizierte Version ist im Download enthalten. Die Klasse TGLBmp bietet nämlich mit AddAlpha(FileName : String) eine einfache Funktion, um den Alphakanal einer Textur aus einer seperaten Datei zu generieren. Wurde der Alphakanal jedoch schon im Bildbearbeitungsprogramm integriert, wird dieser Schritt natürlich nicht mehr benötigt.


procedure TGLForm.LoadTextures;
const
Name : array[0..NumTex-1] of String = ('grass1', 'tree');
...
begin
 for i := 0 to High(Name) do
 begin
  Texture[i] := TGLBmp.Create;
  Texture[i].LoadImage('tex\'+Name[i]+'.tga');
  if Name[i] = 'tree' then
  if not Texture[i].AddAlpha('tex\treealpha.tga') then
   ShowMessage('Couldn''t load Alphamask!');
  Texture[i].GenTexture(False,False);
 end;
...
end;


In unserer Ladeprozedur werden die Texturen wie immer in ein Array geladen und im Falle der Baumtextur wird noch zusätzlich der Alphakanal aus einer anderen Bilddatei generiert.


Schritt 3 - Den Alphakanal nutzen

Nachdem wir unsere Baumtextur also nun mit einem Alphakanal versehen haben, wollen wir diesen natürlich auch nutzen:


procedure TTree.Draw;
begin
 glEnable(GL_BLEND);
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

 glEnable(GL_ALPHA_TEST);
 glAlphaFunc(GL_GREATER, 0.1);

 Texture[1].Bind;
 glPushMatrix;
 glTranslatef(Position.x, Position.y, Position.z);
 glRotatef(Rotation, 0, 1, 0);

 glBegin(GL_QUADS);
  glTexCoord2f(0, 0); glVertex3f(-0.5*Size, 0,      0);
  glTexCoord2f(0, 1); glVertex3f(-0.5*Size, 1*Size, 0);
  glTexCoord2f(1, 1); glVertex3f( 0.5*Size, 1*Size, 0);
  glTexCoord2f(1, 0); glVertex3f( 0.5*Size, 0,      0);
 glEnd;
 glBegin(GL_QUADS);
  glTexCoord2f(0, 0); glVertex3f(0, 0,      -0.5*Size);
  glTexCoord2f(0, 1); glVertex3f(0, 1*Size, -0.5*Size);
  glTexCoord2f(1, 1); glVertex3f(0, 1*Size,  0.5*Size);
  glTexCoord2f(1, 0); glVertex3f(0, 0,       0.5*Size);
 glEnd;
 glPopMatrix;
 glPushMatrix;

 glTranslatef(Position.x, Position.y, Position.z);
 glRotatef(90, 0, 0, 1);
 glColor4f(0,0,0,0.5);
 glBegin(GL_QUADS);
  glTexCoord2f(0, 0); glVertex3f(0.01, 0,      -0.5*Size);
  glTexCoord2f(0, 1); glVertex3f(0.01, 1.5*Size, -0.5*Size);
  glTexCoord2f(1, 1); glVertex3f(0.01, 1.5*Size,  0.5*Size);
  glTexCoord2f(1, 0); glVertex3f(0.01, 0.,      0.5*Size);
 glEnd;
 glColor4f(1,1,1,1);
 glPopMatrix;
 glDisable(GL_ALPHA_TEST);
 glDisable(GL_BLEND);
end;


Der Alphatest wird über den Befehl glEnable mit dem Parameter GL_ALPHA_TEST aktiviert, während mit der Funktion glAlphaFunc die Art des Alphatests festgelegt wird. In obiger Prozedur werden durch den Parameter GL_GREATER nur Pixel mit einem Vergleichswert größer 0.1 durchgelassen. Da dieser Wert bei schwarzen Pixeln < 0.1 ist, werden alle schwarzen Teile der Alphatextur transparent dargestellt. Diesen Parameter kann man als Toleranzgrenze betrachten.

In den Zeilen 7-24 wird unser Baum in Form von zwei in einem Winkel von 90° zueinander stehenden Quads gezeichnet, während in den Zeilen 25-33 der Schatten des Baumes gezeichnet wird. Diese Methode Schatten zu zeichnen ist zwar einfach zu realisieren, sollte jedoch bei unebenen Flächen nicht genutzt werden. Für das Demonstrationsprogramm war der Effekt jedoch ausreichend.


Dies ist alles, was nötig ist um den Alphakanal einer Textur für Transparenzeffekte zu nutzen. Natürlich kann der Alphakanal auch für andere Dinge genutzt werden, aber Alpha Masking ist wohl die häufigste Anwendung.


Das Beispielprogramm

Das Beispielprogramm zu diesem Tutorial wurde in Delphi 6.0 geschrieben, sollte jedoch ab Delphi 4.0 kompilierbar sein. Der Blickwinkel wird mit der Maus verändert, während man sich mit Cursor Hoch/Runter bewegen kann. Da keine speziellen OpenGL-Erweiterungen genutzt werden, sollte es auch auf älteren Grafikkarten lauffähig sein.


Hier noch ein Bild aus dem Demonstrationsprogramm:


Tutorial Alphamasking alphablend01.jpg


Download

Alpha Masking Demo (inklusive Quellcode) herunterladen

Autor: Sascha Willems



Vorhergehendes Tutorial:
Tutorial StereoSehen
Nächstes Tutorial:
Tutorial Wassereffekt

Schreibt was ihr zu diesem Tutorial denkt ins Feedbackforum von DelphiGL.com.
Lob, Verbesserungsvorschläge, Hinweise und Tutorialwünsche sind stets willkommen.