2017-10-18 131 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++中许多包含资源的类一样。