Laden...

[erledigt] devil, tao-framework, funktion iluFlipImage bereitet Darstellungsfehler

Erstellt von Ayke vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.942 Views
Ayke Themenstarter:in
643 Beiträge seit 2006
vor 12 Jahren
[erledigt] devil, tao-framework, funktion iluFlipImage bereitet Darstellungsfehler

Guten Morgen,

ich lese grade ein Buch zu OpenGL und habe daraus Beispiele entnommen.
Um Texturen fur Sprites zu laden benutze ich die Devil Bibliothek die beim
Tao-Framework beiliegt. Eine Funktion bereitet jedoch Probleme "iluFlipImage".
Die ist notwendig da alle Grafiken spiegelverkehrt geladen werden.

Ich verwende .Net 4.0 mit den Tao-Framework 2.1
Bin mir sicher das es nicht an meinen Code liegt da ich es 1:1 übernommen habe und auch schon im Internet recherchiert habe. Vielleicht wisst ihr ja was.

        public void LoadTexture(string textureName, string path)
        {
            int devIlId;
            Il.ilGenImages(1, out devIlId);
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, devIlId);

            if (!Il.ilLoadImage(path))
            {
                System.Diagnostics.Debug.Assert(false,
                "Could not open file, [" + path + "].");
            }

            Ilu.iluFlipImage();

            var width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH);
            var height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT);
            var textureId = Ilut.ilutGLBindTexImage();

            System.Diagnostics.Debug.Assert(textureId != 0);
            Il.ilDeleteImages(1, ref devIlId);
            _textureStorage.Add(textureName, new Texture(textureId, path, width, height));
        }
U
400 Beiträge seit 2008
vor 12 Jahren

Am besten lädst du dir die Textur selber. Da das ja nur in seltenen fällen mehr als ein 4 Zeiler ist und das in jedem Tutorial irgendwannd rann kommt, würd ich das lieber so machen.

Was ist denn genau die Fehlermeldung?

Ayke Themenstarter:in
643 Beiträge seit 2006
vor 12 Jahren

Wie meinst du ich soll die Grafik selber laden. Mit der Bitmap Klasse oder wie ??
Es gibt keine Fehlermeldung es gibt nur Darstellungsfehler wie oben im Bild angehangen.

U
400 Beiträge seit 2008
vor 12 Jahren

Einfach wie in Texture Mapping die Bitmapdaten laden, den Pointer an OGL und wieder freigeben.

Wenn die Darstellung fehlschläg, bist du sicher, dass deine Texturkoordinaten richtig sind?
Ansonsten kanns nurnoch n Parameterfehler in der Methode sein.

Ayke Themenstarter:in
643 Beiträge seit 2006
vor 12 Jahren

So... Jetzt bin ich schon mal ein Stück näher am Ziel. Leider habe ich jetzt um meinen Smiley diese Ecken. Woran kann das liegen ?

Was die 3 Methoden weis ich leider nicht. C&P

 Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGB8, bitmap.Width, bitmap.Height, 0, Gl.GL_BGR_EXT, Gl.GL_UNSIGNED_BYTE, bitmapData.Scan0);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
        public void LoadTexture(string name, string path)
        {
            var bitmap = new Bitmap(path);
            var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                             ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            int textureId;
            Gl.glGenTextures(1, out textureId);
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, textureId);
            Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGB8, bitmap.Width, bitmap.Height, 0, Gl.GL_BGR_EXT, Gl.GL_UNSIGNED_BYTE, bitmapData.Scan0);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);

            _textureStorage.Add(name, new Texture(textureId, path, bitmap.Width, bitmap.Height));

            bitmap.UnlockBits(bitmapData);
            bitmap.Dispose();
        }
Ayke Themenstarter:in
643 Beiträge seit 2006
vor 12 Jahren

Hier nochmal das Originalbild... weil es so schön ist

und hier sehe ich das ich den Alpha- Channel benutze xD Dann wird das wohl irgendwie damit zusammenhängen.

U
400 Beiträge seit 2008
vor 12 Jahren

Verwende einfach folgendes um eine 32bpp Alphachaneltextur zu laden

var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                             ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);

            Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, bitmap.Width, bitmap.Height, 0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, bitmapData.Scan0);

Dann aber die Belndfunction nicht vergessen (sowohl beim erzeugen, als auch beim rendern)

GL.Enable(Blend);
                    GL.BlendFunc(SrcAlpha, OneMinusSrcAlpha);

Da zwar der Alphakanal gesetzt ist, der aber den alpha nicht verwendet. Hier wird dann der alphasource zum blenden verwendet.

Ayke Themenstarter:in
643 Beiträge seit 2006
vor 12 Jahren

Funktioniert wunderbar. Dank dir Pria.

Ayke Themenstarter:in
643 Beiträge seit 2006
vor 12 Jahren

Doch nicht... wenn ich jetzt mehrere Texturen lade gibt es die nächsten Probleme 😦
Siehe Anhang...

Meine Textur Klasse

    public class TextureManager
    {
        private readonly Dictionary<string, Texture> _textureStorage;

        public TextureManager()
        {
            _textureStorage = new Dictionary<string, Texture>();   
        }

        public Texture GetTexture(string textureName)
        {
            return _textureStorage[textureName];
        }

        public void LoadTexture(string name, string path)
        {
            var bitmap = new Bitmap(path);
            var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                             ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
            int textureId;
            Gl.glGenTextures(1, out textureId);
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, textureId);
            Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, bitmap.Width, bitmap.Height, 0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, bitmapData.Scan0);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
            _textureStorage.Add(name, new Texture(textureId, path, bitmap.Width, bitmap.Height));

            bitmap.UnlockBits(bitmapData);
            bitmap.Dispose();
        }
    }

Das laden mit der Textur Klasse

        private void InitializeTextures()
        {
            _textureManager.LoadTexture("font_arial", @"Remove\font_arial.png");
            _textureManager.LoadTexture("stupid_smile", @"Remove\stupid_smile.png");
        }

Meine Render Klasse

        public Renderer()
        {
            Gl.glEnable(Gl.GL_TEXTURE_2D);
            Gl.glEnable(Gl.GL_BLEND);
            Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
        }

        private static void DrawImmediateModeVertex(Vector pos, Color color, Point uvs)
        {
            Gl.glColor4f(color.Red, color.Green, color.Blue, color.Alpha);
            Gl.glTexCoord2f(uvs.X, uvs.Y);
            Gl.glVertex3d(pos.X, pos.Y, pos.Z);
        }

        public void DrawSprite(Sprite sprite)
        {
            Gl.glBegin(Gl.GL_TRIANGLE_STRIP);
            {
                for (var i = 0; i < sprite.VertexAmount; i++)
                {
                    Gl.glBindTexture(Gl.GL_TEXTURE_2D, sprite.Texture.TextureId);
                    DrawImmediateModeVertex(sprite.VertexPositions[i], 
                        sprite.VertexColors[i], sprite.VertexUVs[i]);
                }
            }
            Gl.glEnd();
        }
U
400 Beiträge seit 2008
vor 12 Jahren

Schau dir bitte die Fragen in deinem Quellcode einmal an und versuche diese zu beantworten.


private static void DrawImmediateModeVertex(Vector pos, Color color, Point uvs)
        {
            //Wird hier ein Alphawert gesetzt?, wen ja welcher?
            Gl.glColor4f(color.Red, color.Green, color.Blue, color.Alpha);
            Gl.glTexCoord2f(uvs.X, uvs.Y);
            Gl.glVertex3d(pos.X, pos.Y, pos.Z);
        }

        public void DrawSprite(Sprite sprite)
        {
            Gl.glBegin(Gl.GL_TRIANGLE_STRIP);
            {
                for (var i = 0; i < sprite.VertexAmount; i++)
                {
                    //Warum bindest du hier mehrmals dieselbe Textur?
                    Gl.glBindTexture(Gl.GL_TEXTURE_2D, sprite.Texture.TextureId);
                    DrawImmediateModeVertex(sprite.VertexPositions[i],
                    //Warum setzt du hier mehrmals die Farbe?
                        sprite.VertexColors[i], sprite.VertexUVs[i]);
                }
            }
            Gl.glEnd();
        }

Wann und wo rufst du Renderer auf?
Ich nehme mal an, dass du Renderer auch vor dem laden deiner Texturen aufrufst?

Vor allem bei mir funktionierts einwandfrei. Das Logo in der Mitte und der Text sind jeweils texturierte Quads.

Ayke Themenstarter:in
643 Beiträge seit 2006
vor 12 Jahren

Hallo Pria,

Wird hier ein Alphawert gesetzt?, wen ja welcher?

1

Warum bindest du hier mehrmals dieselbe Textur?

Der TextureManager lädt zuerst alle Texturen die ich später benötigen werde.
Die Id der Texture speicher ich in einer Dictionary mit einen eindeutigen String zum abrufen.
Beim Rendern binde ich die TextureId erneut damit ich beim Zeichnen die richtige Textur verwende. Gibt es vielleicht sowas wie unbind texture ??

Warum setzt du hier mehrmals die Farbe?

Tue ich nicht, jeder Vertext bekommt eine Farbe verpasst.

Wann und wo rufst du Renderer auf?
Ich nehme mal an, dass du Renderer auch vor dem laden deiner Texturen aufrufst?

Den Renderer rufe ich ganz am Ende auf.

U
400 Beiträge seit 2008
vor 12 Jahren

Alles klar, dann mach doch folgendes:

  1. Den Renderer (also deine methode, in der du blending und so setzt) ganz am ANFANG deiner Darstellungsschleife aufrufen, da du sonst erst auf Texturen zugreifst und diese dann erst verfpgbar machst.

  2. Wenn du einen Alphawert setzt, überschreibst du die Farbe deiner Textur und diese wird wiederum sichtbar. Verwende statdessen Color3f

  3. Etwas grundlegendes über OpenGL "OpenGL ist eine Zustandmaschine, dass heißt, dass ein gesetzter Zustand bis zu dessen Aufhebung aktiv bleibt".
    Du musst lediglich ein mal vor dem Aufruf von Gl.Begin eine Textur binden, die dann auf die in Gl.Begin definierte Struktur angewendet wird. Um eine Textur wieder zu "entladen" verwende einfach Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0);

Warum setzt du hier mehrmals die Farbe?
Tue ich nicht, jeder Vertext bekommt eine Farbe verpasst.

Dann solltest du keine Texturen verwenden oder eben die Farbe auf 3 Komponenten reduzieren.

Ayke Themenstarter:in
643 Beiträge seit 2006
vor 12 Jahren

Problem gelöst. War der Dispose der Bitmap.

        public void LoadTexture(string name, string path)
        {
            var bitmap = new Bitmap(path);
            var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                             ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
            int textureId;
            Gl.glGenTextures(1, out textureId);
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, textureId);
            Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, bitmap.Width, bitmap.Height, 0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, bitmapData.Scan0);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
            _textureStorage.Add(name, new Texture(textureId, path, bitmap.Width, bitmap.Height));

            //HIER LIEGT DER HUND BEGRABEN !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            bitmap.UnlockBits(bitmapData);
            bitmap.Dispose();
        }