OpenGL Texture Mipmaps generieren, immer noch Fehler



  • Hi Leute,

    eigentlich sollte das ja kein großes Problem sein, aber mein Programm macht immer noch Fehler, d.h. mein Programm stürtzt zu 50% Wahrscheinlichkeit beim Starten ab, wenn ich zu viele Mipmaps generiere - müsste also ein Pointer Fehler sein.

    Das Prinzip und eigentlich auch die Technik von Texture-Mipmaps habe ich verstanden.
    Aber merkwürdiger Weise sind auf der vorletzten Mipmap Stufe meiner generierten Texturen fast überall bunte Farben die absolut nicht in den restlichen Michmasch reinpassen. Das hat mich schon auf die Idee gebracht, dass es ein Pointer Fehler sein muss, sowas kann schließlich passieren, wenn ein Pointer auf irgendeinen Speicher mit irgendwelchen Werten zeigt.

    Aber ich hab' den Teil meines Programm nun schon sooo lange unter die Lupe genommmen, wieder Sachen verändert, noch mehr vereinfacht um Klarheit in meinen Code zu bringen, es hilft aber alles nichts.

    Hier ein Beispiel Bild des Fehlers:

    http://softpixelengine.sourceforge.net/other/DemoImage.bmp

    Hier ist der Code Teil:

    template <typename T> void spDeleteArray(T* &pBuffer)
    {
        if (pBuffer)
        {
            delete [] pBuffer;
            pBuffer = 0;
        }
    }
    
    void TextureManager::scaleHalfImageData(u8* &ImageData, s32 Width, s32 Height, s32 InternalFormat)
    {
    
        /* Temporary variables */
        register s32 x, y, i;
    
        /* New image data size */
        s32 NewWidth    = Width;
        s32 NewHeight   = Height;
    
        /* Change the new size */
        if (NewWidth > 1)
            NewWidth >>= 1;
        if (NewHeight > 1)
            NewHeight >>= 1;
    
        /* Save the old image data */
        u8* OldImageData = ImageData;
    
        /* Allocate new image data */
        ImageData = new u8[ NewWidth * NewHeight * InternalFormat ];
    
        if (Width > 1 && Height > 1)
        {
    
            /* Loop for the half image size */
            for (y = 0; y < NewHeight; ++y)
            {
                for (x = 0; x < NewWidth; ++x)
                {
                    for (i = 0; i < InternalFormat; ++i)
                    {
                        /* Fill the current new data elements */
                        ImageData[ ( y * NewWidth + x ) * InternalFormat + i ] = (
                            OldImageData[ ( ((y << 1)    ) * Width + ((x << 1)    ) ) * InternalFormat + i ] +
                            OldImageData[ ( ((y << 1)    ) * Width + ((x << 1) + 1) ) * InternalFormat + i ] +
                            OldImageData[ ( ((y << 1) + 1) * Width + ((x << 1)    ) ) * InternalFormat + i ] +
                            OldImageData[ ( ((y << 1) + 1) * Width + ((x << 1) + 1) ) * InternalFormat + i ]
                        ) / 4;
                    } // next color component
                } // next pixel
            } // next line
    
        }
        else if ( ( Width > 1 && Height == 1 ) || ( Width == 1 && Height > 1 ) )
        {
    
            s32 size = math::Max(NewWidth, NewHeight);
    
            /* Loop for the half image size */
            for (x = 0; x < size; ++x)
            {
                for (i = 0; i < InternalFormat; ++i)
                {
                    /* Fill the current new data elements */
                    ImageData[ x * InternalFormat + i ] = (
                        OldImageData[ ( (x << 1)     ) * InternalFormat + i ] +
                        OldImageData[ ( (x << 1) + 1 ) * InternalFormat + i ]
                    ) / 2;
                } // next color component
            } // next pixel
    
        }
    
        /* Delete the old image data */
        delete [] OldImageData;
    
    }
    
    void OpenGLDriver::build2DMipmaps(s32 InternalFormat, s32 Format, s32 Width, s32 Height, const u8* ImageData)
    {
        /* Check the internal format value */
        checkInternalFormat(InternalFormat);
    
        /* Temporary memories */
        s32 i                   = 0;
        u8* pData               = 0;
        const s32 ImageDataSize = Width*Height*InternalFormat;
    
        dim::size2di Size(Width, Height);
    
        /* Allocate new image data memory */
        pData = new u8[ImageDataSize];
    
        /* Copy the image data */
        memcpy(pData, ImageData, ImageDataSize);
    
        /* Get the optimized size & scale if the input size is not correct */
        TextureManager::checkImageSize(Size);
    
        /* Get the maximal size */
        GLint MaxSize;
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxSize);
    
        /* Check the size of maxima */
        if (Size.Width > MaxSize)
            Size.Width = MaxSize;
        if (Size.Height > MaxSize)
            Size.Height = MaxSize;
    
        /* Clamp the image data size, must be power of to (2^n) */
        if (Size.Width != Width || Size.Height != Height)
            TextureManager::scaleImageData(pData, Width, Height, Size.Width, Size.Height, InternalFormat);
    
        /* Loop for all mipmap levels */
        while (1)
        {
            /* Build a new mipmap level */
            glTexImage2D(GL_TEXTURE_2D, i++, InternalFormat, Size.Width, Size.Height, 0, Format, GL_UNSIGNED_BYTE, pData);
    
            /* Check if the last mipmap level has been achieved */
            if (Size.Width == 1 && Size.Height == 1)
                break;
    
            /* Scale the image data to the half size */
            TextureManager::scaleHalfImageData(pData, Size.Width, Size.Height, InternalFormat);
    
            /* Half the size */
            if (Size.Width > 1)
                Size.Width >>= 1;
            if (Size.Height > 1)
                Size.Height >>= 1;
        }
    
        /* Delete temporary memory */
        spDeleteArray(pData);
    }
    

    Ich hoffe ihr könnt mir helfen, an diesem Problem verzweifle ich schon seit ca. 5 Monaten 😞

    Danke schonmal


  • Mod

    wie sehen die mipmaps aus wenn du sie dir als bilder auf hdd ablegst?



  • Also ich das das Letzte Mal gemacht habe (mind. schon zwei mal getestet) war die vorletzte Stufe mit der Windows Faxanzeige nicht einzusehen und mit Zeichnenprogrammen - z.b. das ganz einfache Paint - waren dort (soweit ich mich entsinne) auch bunte Pixel zu sehen.

    Aber ich teste das lieber nochmal um euch genauere Details dazu zu sagen.



  • Also ich hab' jetzt noch mal einen recht guten Debug Teil geschrieben.
    Ich lasse mir alle Mipmaps einer Texture in einer Bitmap-Bild-Datei (bmp) ausgeben.
    Dort sieht alles wunderbar aus. 😮
    Keine Ahnung warum das im Programm selbst so komisch aussieht.


  • Mod

    was meinst du mit 'im program selbst', hast du die BMP in einer extra applikation erstellt? schreib einfach genau an der stelle im program selbst die bmps raus 😉



  • 'im program selbst' heißt, dass das Programm die vorletzte Mipmap Stufe falsch anzeigt (wie auf meinem Link des ersten Beitrags zu erkennen) es aber komischer Weise als BMP richtig abspeichert.
    Ich hab' kein extra Programm dafür geschrieben sondern genau das getan, was du mir auch vorgeschlagen hast.
    Ich hatte ganz einfach die Funktionen zum Speichern der Bitmaps files zwischen den Code der "build2DMipmaps" Funktion mit Compiler-Directieven ("#ifdef __DEBUG_MIPMAPS__" etc.)


  • Mod

    dann mach das noch an der stelle an der du die mipmap an opengl uebergibst und zusaetzlich forder die textur wieder von opengl an (ich glaube glReadPixels oder so?) und speicher das ab, wenn es haar genau vorher richtig ist und danach falsch, setzt du einen parameter eventuell falsch
    ansonsten weisst du wenigstens ob es vorher schief geht.



  • Wenn ich GL_RGBA und eben 4 Farbkomponenten nehme funktioniert das Einwandfrei.
    Das verstehe ich nicht.
    Wenn ich mir die Werte von OpenGL wieder geben lasse, mit "glGetTexImage" ist auch noch alles in Butter, nur die Anzeige stimmt nicht und das sorgt sogar oft zu Abstürtzen.



  • Mit der OpenSource Funktion "gluBuild2DMipmaps" funktioniert es, jedenfalls stürtzen dann die Programme auch nicht manchmal, sondern gar nicht ab und die misteriösen Pixel Farben erscheinen nicht, dafür werden die Mipmaps sehr hässlich erstellt.

    Das einzige was mich an der Funktion wundert ist, dass mit "malloc" (Width+4)*Height*Components*bpp allokiert wird. Warum (Widht+4)??

    Also ich allokiere einfach nur Width*Height*InternalFormat (z.b. 128*128*3) mit dem C++ Keyword "new". Ist das denn so richtig? Müsste eigentlich oder?!



  • Also ich hab' das Problem jetzt erst mal vorläufig 'gelöst'.
    Allerdings klappt das nur wenn ich den ImageData pointer immer auf 4 Farbkomponenten (RGBA) convertiere und dann immer eine OpenGL Texture mit GL_RGBA erstelle. Mit GL_RGB, GL_LUMINANCE usw. taucht der schwerwiegende Fehler immer wieder auf 😞
    Ganz zufrieden bin ich mit der Lösung nicht, aber immer hin stürtzt das Programm nicht mehr ab und die Texturen sehen ganz normal aus.


Log in to reply