2017-10-18 134 views
-1

我想爲我的項目創建一個紋理類,它初始化並從圖像加載紋理。紋理加載情況良好,但每當我想通過調用GetTexture()函數從類外部獲取紋理ID時,glIsTexture()不會將返回值(紋理ID)視爲紋理。我想紋理的臉部保持空白。我試圖用Texture :: SetActive()函數直接從Texture類本身綁定glBindTexture()的紋理,但它仍然不起作用。紋理綁定不工作/ C++/OpenGL

最後,當我直接從函數返回紋理ID時,紋理顯示正確。

有什麼我在這裏失蹤?在這一點上,我真的不知道要尋找什麼。

在此先感謝您的幫助!

這裏是我的Texture類:

// Constructor 
Texture::Texture(std::string const& texPath) { 

    SDL_Surface *texture = nullptr, *newFormatTexture = nullptr, *flippedTexture = nullptr; 
    SDL_PixelFormat tmpFormat; 
    Uint32 amask, rmask, gmask, bmask; 

#if SDL_BYTEORDER == SDL_BIG_ENDIAN 

    rmask = 0xFF000000; 
    gmask = 0x00FF0000; 
    bmask = 0x0000FF00; 
    amask = 0x000000FF; 

#else 

    rmask = 0x000000FF; 
    gmask = 0x0000FF00; 
    bmask = 0x00FF0000; 
    amask = 0xFF000000; 

#endif 

    if ((texture = IMG_Load(texPath.c_str())) == nullptr) { 
     std::cerr << "[ERROR] : Could not load texture " << texPath << ". Skipping..." << std::endl; 
    } 

    tmpFormat = *(texture->format); 
    tmpFormat.BitsPerPixel = 32; 
    tmpFormat.BytesPerPixel = 4; 
    tmpFormat.Rmask = rmask; 
    tmpFormat.Gmask = gmask; 
    tmpFormat.Bmask = bmask; 
    tmpFormat.Amask = amask; 

    if ((newFormatTexture = SDL_ConvertSurface(texture, &tmpFormat, SDL_SWSURFACE)) == nullptr) { 
     std::cerr << "[ERROR] : Couldn't convert surface to given format." << std::endl; 
    } 

    if ((flippedTexture = this->FlipSurface(newFormatTexture)) == nullptr) { 
     std::cerr << "[ERROR] : Couldn't flip surface." << std::endl; 
    } 

    glGenTextures(1, &(this->_textureID)); 

    glBindTexture(GL_TEXTURE_2D, this->_textureID); 

    glTexImage2D(GL_TEXTURE_2D, 0, 4, flippedTexture->w, flippedTexture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, flippedTexture->pixels); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

    glBindTexture(GL_TEXTURE_2D, 0); 

    SDL_FreeSurface(flippedTexture); 
    SDL_FreeSurface(newFormatTexture); 
    SDL_FreeSurface(texture); 

} 

Texture::Texture(unsigned char *texData, int width, int height) { 

    glGenTextures(1, &(this->_textureID)); 
    glBindTexture(GL_TEXTURE_2D, this->_textureID); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, texData); 
    glBindTexture(GL_TEXTURE_2D, 0); 

} 

Texture::~Texture() { 
    glDeleteTextures(1, &(this->_textureID)); 
} 

Texture Texture::CreateTexture(std::string const& texPath) { 

    Texture tex(texPath); 
    return (tex); 
} 

Texture Texture::CreateTexture(unsigned char *texData, int width, int height) { 

    Texture tex(texData, width, height); 
    return (tex); 
} 

unsigned int Texture::GetTexture() const { 
    return (this->_textureID); 
} 

void Texture::SetActive() { 
    glBindTexture(GL_TEXTURE_2D, this->_textureID); 
} 

主類,我加載並使用我的質地:

int WinMain(void) { 

    Window window("Hello", 640, 480); 
    double angleX, angleZ; 
    Texture tex; 
    int height; 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(70, (double)640/480, 1, 1000); 
    glEnable(GL_TEXTURE_2D); 
    glEnable(GL_DEPTH_TEST); 

    tex = Texture::CreateTexture("caisse.jpg"); 

    while (!window.Quit()) { 

     Input::Update(); 

     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     glMatrixMode(GL_MODELVIEW); 
     glLoadIdentity(); 
     gluLookAt(3,4,2,0,0,0,0,0,1); 

     tex.SetActive(); 

     glBegin(GL_QUADS); 

      glTexCoord2d(0, 1); 
       glVertex3d(1, 1, 1); 

      glTexCoord2d(0, 0); 
       glVertex3d(1, 1, -1); 

      glTexCoord2d(1, 0); 
       glVertex3d(-1, 1, -1); 

      glTexCoord2d(1, 1); 
       glVertex3d(-1, 1, 1); 

     glEnd(); 

     glFlush(); 
     window.RefreshDisplay(); 
    } 

    return (0); 
} 

編輯

我解決我的問題。 正如本主題所述:What are the usual troubleshooting steps for OpenGL textures not showing?,紋理的初始化不能在構造函數中完成。

感謝您的幫助:)

+0

你爲什麼:1)做了很多'this - > _ someName'?把下劃線放在前面的*整點*是讓人們知道它是一個成員。 'this->'是沒有意義的。 2)總是用括號包圍返回值?這實際上可以抑制某些優化。 –

回答

0

OK,讓我們來看看這個:

Texture Texture::CreateTexture(std::string const& texPath) { 

    Texture tex(texPath); 
    return (tex); 
} 

我會認爲這是一個靜態函數。所以它會在堆棧上創建一個Texture對象。並且tex包含一個OpenGL紋理對象。該函數然後返回這個對象。

按照C++的規則,tex的生存期限制在它創建的範圍內。即,Texture::CreateTexture。這意味着,在該函數結束時,tex將通過調用析構函數而銷燬。

但是由於您返回了tex,在此之前,tex將用於初始化函數的返回值。該返回值恰好是Texture類型的對象,因此編譯器將調用Texture的拷貝構造函數來初始化返回值。

所以,tex被破壞權利之前,有兩個Texture對象:tex本身和從tex複製Texture類型的返回值。到現在爲止還挺好。

現在,tex被銷燬。 Texture::~Texture在其中包含的紋理對象上調用glDestroyTexture。這破壞了構造函數中創建的紋理。精細。

那麼......現在會發生什麼?那麼,讓我們回到從CreateTexture創建返回值。我說它會調用Texture的拷貝構造函數來構造它,傳遞tex作爲從中複製的對象。

你不發表您的完整代碼,但鑑於你寫的其他代碼的性質,我敢打賭,你沒有寫拷貝構造函數Texture。這很好,因爲編譯器會爲你製作一個。

只是這不好。爲什麼?因爲在tex之前被破壞,所以有兩個對象Texture。和兩者都存儲相同的OpenGL紋理對象名稱。那是怎麼發生的?

因爲您將紋理對象從tex複製到返回值中。這就是編譯器生成的拷貝構造函數所做的事情:它複製類中的所有內容。

所以當tex被破壞時,它正在破壞OpenGL紋理它剛剛返回了

Texture不應該是可複製的類。它應該是僅移動的,就像C++中許多包含資源的類一樣。