[SDL,OpenGL] Texturen werden in manchen Builds nicht gerendert



  • Guten Morgen,

    ich habe das Problem, dass Texturen in manchen Builds meines Programmes nicht angezeigt werden. Es scheint, als wäre es ein Fall von undefiniertem Verhalten, doch ich finde leider den Fehler nicht.

    Hier die vollständige Klasse Textur mit Ausgabe zu Debug-Zwecken:

    #include "textur.h"
    
    using namespace fabula;
    
    Textur::Textur(const std::string &filename) :
        filename_(filename)
    {
        if (filename_ != "")
        {
            textur_ = init(filename_);
            empty   = false;
            std::cout << filename_ << " : " << filename << " Nor w/ file"<< std::endl;
        } else {
            empty   = true;
            std::cout << filename_ << " Nor w/o file"<< std::endl;
        }
    }
    
    // Copy
    Textur::Textur(const Textur &textur) :
        filename_(textur.filename_)
    {
        if (filename_ != "")
        {
            textur_ = init(filename_);
            empty   = false;
            std::cout << filename_ << " : " << textur.filename_ <<  " Copy w/ file"<< std::endl;
        } else {
            empty   = true;
            std::cout << filename_ << " : " << textur.filename_ <<  " Copy w/o file"<< std::endl;
        }
    }
    
    Textur::~Textur()
    {
        glDeleteTextures(1, &textur_);
    }
    
    Textur& Textur::operator=(const std::string &filename)
    {
        glDeleteTextures(1, &textur_);
        filename_ = filename;
    
        if (filename_ != "")
        {
            textur_ = init(filename_);
            empty   = false;
            std::cout << filename_ << " : " << filename <<  " Nor= w/ file"<< std::endl;
        } else {
            textur_ = 0;
            empty   = true;
            std::cout << filename_ << " : " << filename <<  " Nor= w/o file"<< std::endl;
        }
        return *this;
    }
    
    // Copy
    Textur& Textur::operator=(const Textur &textur)
    {
        glDeleteTextures(1, &textur_);
        filename_ = textur.filename_;
    
        if (filename_ != "")
        {
            textur_ = init(filename_);
            empty   = false;
            std::cout << filename_ << " : " << textur.filename_ <<  " Copy= w/ file" << empty<< std::endl;
    
        } else {
            textur_ = 0;
            empty   = true;
            std::cout << filename_ << " : " << textur.filename_ <<  " Copy= w/ file"<< std::endl;
    
        }
    
        return *this;
    }
    
    std::string& Textur::getFilename()
    {
        return this->filename_;
    }
    
    GLuint& Textur::init(const std::string &filename)
    {
        SDL_Surface *image = IMG_Load( filename.c_str() );
    
        SDL_Surface *imageFormated = SDL_DisplayFormatAlpha(image);
    
        textur_ = 0;
    
        glGenTextures(1, &textur_);
    
        glBindTexture(GL_TEXTURE_2D, textur_);
    
        //Texture behaving
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
    
        //Free Surface
        SDL_FreeSurface(imageFormated);
        SDL_FreeSurface(image);
    
        return textur_;
    }
    
    int Textur::bind()
    {
        glBindTexture(GL_TEXTURE_2D, textur_);
        return 0;
    }
    
    GLuint& Textur::toGL()
    {
        return textur_;
    }
    

    Textur nutze ich als Attribut der Klasse Panel , von der nur die Konstruktoren wichtig sein sollten:

    Panel::Panel()
        : xPos_(0), yPos_(0), width_(0), height_(0), alpha_(255)
        , texture_(FABULA_NULLTEX),draw_(false)
    {}
    
    Panel::Panel(float x,float y,float w, float h, const std::string &fileName, bool draw)
        : xPos_(x), yPos_(y), width_(w), height_(h), alpha_(255)
        , texture_(fileName),draw_(draw)
    {}
    
    // Copy
    Panel::Panel( const Panel& panel )
        : xPos_(panel.xPos_), yPos_(panel.yPos_), width_(panel.width_), height_(panel.height_), alpha_(panel.alpha_)
        , texture_(panel.texture_),draw_(panel.draw_)
    {}
    
    Panel& Panel::operator=( const Panel& panel )
    {
        xPos_   = panel.xPos_;
        yPos_   = panel.yPos_;
        width_  = panel.width_;
        height_ = panel.height_;
        alpha_  = panel.alpha_;
        texture_= panel.texture_;
        draw_   = panel.draw_;
    
        return *this;
    }
    

    Definiert wird ein Objekt der Klasse Panel folgendermaßen:

    #define IMG_MENU_BG         ".graphic/background/menu.png"
    
    std::cout << "bg_ erstellen" << std::endl;
    bg_     = { 0,0,WINDOW_WIDTH,WINDOW_HEIGHT,IMG_MENU_BG,true };
    

    Die Ausgabe an dieser Stelle sieht also in jedem Fall, egal ob das Bild angezeigt wird, oder nicht, so aus:

    bg_ erstellen
    .graphic/background/menu.png : .graphic/background/menu.png Nor w/ file
    .graphic/background/menu.png : .graphic/background/menu.png Copy= w/ file0

    Das Rendern wird durch diese Funktion eingeleitet:

    bool Panel::draw()
    {
        if ( !draw_ )
        {
            return 0;
        }
    
        if ( texture_.empty == true )
        {
            panelStd( xPos_ , yPos_ , width_ , height_ );
        } else {
            panelAlpha( xPos_ , yPos_ , width_ , height_ , texture_.toGL(), alpha_ );
        }
    
        return 1;
    }
    

    Aus irgendeinem Grund ist also das Attribut Textur::empty , das laut Ausgabe false sein sollte, plötzlich true .

    Wie gesagt: Ob die Textur angezeigt wird, oder nicht, ändert sich von Build zu Build. Ich habe dieses mal extra mehr Code in den Post gepackt und hoffe, dass der Fehler irgendwo dort liegt. Ich finde ihn leider nicht und bitte daher um Hilfe.

    Mit freundlichen Grüßen,
    Ki



  • Ersetz mal

    if (filename_ != "")
    

    durch

    if (filename_.length() != 0)
    


  • MisterX schrieb:

    Ersetz mal

    if (filename_ != "")
    

    durch

    if (filename_.length() != 0)
    

    Das ist eleganter, hilft bei dem Problem aber leider nicht.

    EDIT:
    Ungewöhnlicher Weise tritt das Problem übrigens nie bei Objekten der Klasse Panel_Button auf.

    Panel_Button::Panel_Button(int index, float x,float y,float w, float h, const std::string &fileName, bool draw) :
    Panel(x, y, w, h, fileName, draw),
    bIndex_(index)
    {}
    


  • Da hilft wohl nix...
    Du must den Ablauf mit dem Debugger verfolgen und die Stelle finden wo es zum ersten mal falsch ist.

    Es gibt ja nur einige Möglichkeiten wie es passieren kann:

    1. Die Ausführung erreicht ein

    empty   = true;
    

    womit du nicht gerechnet hast.

    2. Die Variablen sind irgendwie in einem lokalen Gültigkeitswbereich und die erwarteten Änderungen werden nicht global, wie du es erwartest.

    3. Ein Seiteneffekt den Du nicht bedacht hast wirkt auf die Variable

    4. Du überschreibst irgendwo fremden Speicher und triffst genau diese Variable
    (ist eher unwahrscheinlich)

    Mehr möglichkeiten fallen mir nicht ein, wie so eine "geisterhafte" Änderung eintreten kann.



  • Ich bin jetzt von Ubuntu nach Fedora migriert und der Fehler tritt seltsamerweise nicht mehr auf.

    Vorsichtshalber lasse ich den Thread aber besser offen, da ich diesen seltsamen Bug und sein Verschwinden absolut nicht nachvollziehen kann.


Anmelden zum Antworten