OpenGL/Glut - Alpha channel simulieren
-
Hallo!
Ich habe ein kleines Problem mit Glut. Ich habe ein Programm geschrieben, welches *.bmp Bilder (18+RGB) Dateien liest und darstellt. Dafür benutze ich die Glut-Funktion glDrawPixels(...).
Allerdings kann ich jetzt nur rechteckige Bilder zeichnen. Nun will ich aber mehrere Bilder zeichnen, die sich überlagern und dafür brauche ich eine Transparenz/transparente Farbe. Ich glaube, das lässt sich mit einem alpha-channel machen, aber *.bmp Dateien haben (normalerweise) keinen.
Wie kann ich nun festlegen, dass eine Farbe transparent bzw. unsichtbar wird?
Kann ich einfach einen neuen Array machen und hinter einem bistimmten RGB-code (z.B. 255,255,255, also weiß) einfach einen Alpha-Channel von 255 eintragen? (Darum der Titel: A.C. simulieren)
Oder lässt sich das bequem mit einer Glut-Funktion machen?
Hier erstmal der Quellcode:#include <GL/glut.h> #include <stdio.h> #include <string> using namespace std; #define ImageWidth 64 #define ImageHeight 64 #define ScreenW 640 #define ScreenH 480 unsigned char tex2[ImageWidth*ImageHeight*3]; //array für reine Bilddaten string file; void LoadImage(string file) { unsigned char tex[ImageWidth*ImageHeight*3 + 18*3];//array als bmp container unsigned char temp; //tausch-variable FILE * pFile; pFile=fopen(file.c_str(),"r"); fread(tex,ImageWidth*ImageHeight*3 + 18*3,1,pFile); fclose(pFile); for (int num = 18*3-1; num < ImageWidth*ImageHeight*3 +18*3; num = num + 1) { //ersten 18 Pixel entfernen, nur Infos über das Bild... tex2[num - 18*3] = tex[num]; } for (int num = 0; num < ImageWidth*ImageHeight*3; num = num + 3) { //Bitmap umdrehen temp = tex2[num]; tex2[num] = tex2[num+2]; tex2[num +2] = temp; } } void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); LoadImage("rockchecker2.bmp"); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); } float YPixToRas(float pix) { return (1.0-ImageHeight*(1.0/(ScreenH/2.0)))-(2.0/ScreenH)*pix; } float XPixToRas(float pix) { return -1.0+(2.0/ScreenW)*pix; } void display(void) { glClear(GL_COLOR_BUFFER_BIT); init(); glRasterPos2f(XPixToRas(100), YPixToRas(100)); glDrawPixels(ImageWidth, ImageHeight, GL_RGB, GL_UNSIGNED_BYTE, tex2); glFlush(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA); glutInitWindowPosition(100,100); glutInitWindowSize(ScreenW,ScreenH); glutCreateWindow("E-X-T-I-N-C-T-I-O-N"); glutDisplayFunc(display); glutMainLoop(); return 0; }Naja, sieht nicht besonders schön aus, aber ist ja nur zum testen.

Ich benutze zum compilieren Eclipse unter Ubuntu 7.10.
Währe nett, wenn mir jemand weiterhelfen könnte.
MfG
Extinction
-
das bmp-format kennt durchaus alpha-kanaele aber es gibt aeusserst wenige programme die damit umgehen koennen. ich wuerde dir empfehlen von vorne herein einen vernuenftigen alpha-kanal (mit abstufungen wegen bilinearem filter) zu erzeugen und in einem geeigneten format (zb png oder tga) zu speichern.
du benutzt dann dein bitmap als textur auf einem polygon und aktivierst eine geeignete blend-funktion und/oder alpha-test.
alternativ kannst du auch einen alpha-kanal programmatisch erzeugen.
eine bestimmte farbe "automatisch" transparent zu machen unterstuetzt opengl nicht.
-
Also bei einer bmp geht das nur, wenn ich sie als Textur auf einem Polygon verwende und eine blend-funktion benutze? Ich denke, da lässt sich besser eine png Datei verwenden, vor Allem auch wegen der Dateigröße. Aber wie läd man png's? Gibt es dazu ein Tutorial?
Mit Google finde ich nur C Beispielcodes.
Edit: Das Splatlogo Beispiel hier:
http://www.opengl.org/resources/code/samples/glut_examples/examples/examples.html
Sieht mir eigentlich nach dem aus, was ich suche, aber es funktioniert leider nicht richtig.
Ich habe dafür noch die Variablen definiert:int logo_width=64; int logo_height=64; unsigned char logo_image[]="Test.png";und bekomme noch die Warnung:
Warnung: geschweifte Klammern fehlen um Initialisierung für »GLfloat [3]« main.cpp line 35
-
Also bei einer bmp geht das nur, wenn ich sie als Textur auf einem Polygon verwende und eine blend-funktion benutze? Ich denke, da lässt sich besser eine png Datei verwenden, vor Allem auch wegen der Dateigröße.
Meine Aussage war unabhaengig vom Dateiformat.
Aber wie läd man png's? Gibt es dazu ein Tutorial?
Zb indem man libpng einbindet.
Das Beispiel [...] funktioniert leider nicht richtig.
Konkret.
und bekomme noch die Warnung:
geschweifte Klammern fehlen um Initialisierung für »GLfloat [3]« main.cpp line 35Und was steht in "line 35" so?
-
Ok, die werde ich mir mal anschauen.
typedef struct _SplatInfo { int x, y; GLboolean alphaTest; GLfloat xScale, yScale; GLfloat scale[3]; GLfloat bias[3]; } SplatInfo; int winHeight; int numSplats = 0; SplatInfo splatConfig; SplatInfo splatList[MAX_SPLATS]; SplatInfo splatDefault = { 0, 0, GL_TRUE, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, }; // <---- Zeile 35 void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, w, 0, h); glMatrixMode(GL_MODELVIEW); winHeight = h; }Das hat vlt. etwas damit zu tun, dass das struct mit GLfloat scale[3]; definiert wurde und dann eines mit 1.0, 1.0, 1.0, initialisiert wird. Ich weis auch nicht, ob das so in c++ funktioniert...
-
Sorry für den Doppelpost, aber ich wollte nicht extra einen neuen Thread aufmachen.
Ich hab das jetzt soweit hinbekommen:
BMP's und PNG's laden funktioniert. (PNG's mit Alpha-channel)
Die Textur wird auch korrekt auf das Polygon gezeichnet.Nun musste ich schmerzlich feststellen, dass es jetzt ziemlich schwierig ist, das Bild richtig zu positionieren, da Polygone ja nur in einer 3D-Umgebung angezeigt werden können (ja, ich weis, das fällt mir spät ein...). Ich will ja ein (wenn auch kleines) 2D Spiel machen. Dafür muss ich auch Bilder nach Pixeln positionieren können, damit immer das Bild richtig ausgefüllt wird.
Kann ich das nun noch irgendwie mit glDrawPixels hinbekommen? Also mein RGBA Bild zeichnen?
Oder wie justiere ich die Kamera am besten, damit sie auf die Polygone zeigt?
-
Nunja, glDrawPixels uebertraegt die Daten aus dem Hauptspeicher was ein bischen an den Vorteilen von Hardwarebeschleunigung vorbei zielt.
Sofern Deine Sprites mit vernuenftigem Anti-Aliasing gezeichnet sind (also nicht unter bilinearem Filtering leiden), besteht keine Notwendigkeit, diese an ganzzahligen Pixelposition auszurichten.
Du kannst dann entweder orthogonale Projektion nutzen oder die Polygone so im Frustum positionieren, dass deren x,y-Translation Pixelpositionen entsprechen.
-
Danke!
Die orthogonale Projektion funktioniert ganz gut, was das positionieren etc. angeht.
Allerdings werden transparenzen ignoriert. Woran kann das liegen? Ich hab die Textur eigentlich genau so benutzt, wie in einer 3D Ansicht.Edit: Sorry, mein Fehler. Habe aus Versehen das alpha-Blending mit den anderen 3D Befehlen gelöscht...