【问题标题】:Opengl C++: texture code textures all models with the same textureOpengl C++:纹理代码纹理所有具有相同纹理的模型
【发布时间】:2014-12-23 13:01:06
【问题描述】:

我创建了一个类来保存我的模型信息。我必须正确渲染模型并正确包装纹理,但由于某种原因,如果我有多个模型,它会将我的所有模型纹理化为仅 1 个纹理,如您在这张图片中看到的:http://imgur.com/d0glIwF

任何想法为什么会发生这种情况?

这是我的代码:

struct BitMapFile
{
   int sizeX;
   int sizeY;
   unsigned char *data;
};


// Routine to read a bitmap file.
// Works only for uncompressed bmp files of 24-bit color.
BitMapFile *getBMPData(string filename)
{
   BitMapFile *bmp = new BitMapFile;
   unsigned int size, offset, headerSize;

   // Read input file name.
   ifstream infile(filename.c_str(), ios::binary);

   // Get the starting point of the image data.
   infile.seekg(10);
   infile.read((char *) &offset, 4); 

   // Get the header size of the bitmap.
   infile.read((char *) &headerSize,4);

   // Get width and height values in the bitmap header.
   infile.seekg(18);
   infile.read( (char *) &bmp->sizeX, 4);
   infile.read( (char *) &bmp->sizeY, 4);

   // Allocate buffer for the image.
   size = bmp->sizeX * bmp->sizeY * 24;
   bmp->data = new unsigned char[size];

   // Read bitmap data.
   infile.seekg(offset);
   infile.read((char *) bmp->data , size);

   // Reverse color from bgr to rgb.
   int temp;
   for (int i = 0; i < size; i += 3)
   { 
      temp = bmp->data[i];
      bmp->data[i] = bmp->data[i+2];
      bmp->data[i+2] = temp;
   }

   return bmp;
}

class Model
{
public:
    Model(string modelFilename, string textureFilename);

   float getCenterX() { return m_CenterX; }
   float getCenterY() { return m_CenterY; }
   float getCenterZ() { return m_CenterZ; }
   void SetCenterX(float x) { m_CenterX = x; }
   void SetCenterY(float y) { m_CenterY = y; }
   void SetCenterZ(float z) { m_CenterZ = z; }

    void LoadTexture(string fileName);
    //load model function
    void Draw();
private:

    float m_CenterX, m_CenterY, m_CenterZ, m_Width, m_Height, m_Depth;

    string m_ModelFilename;

    int m_Texture;
        string m_TextureName;
};
Model::Model(string modelFilename, string textureFilename)
{
    m_ModelFilename = modelFilename;
    m_TextureName = textureFilename;

    //load model function//
    LoadTexture(m_TextureName);
}

void Model::LoadTexture(string TextureName)         
{
   // Local storage for bmp image data.
   BitMapFile *image[1];

        string filename = TextureName;
        filename.append(".bmp");

       // Load the texture.
       image[0] = getBMPData(filename);

       // Bind grass image to texture index[i]. 
       glBindTexture(GL_TEXTURE_2D, m_Texture); //makes room for our texture
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
       glTexImage2D(GL_TEXTURE_2D, //always GL_TEXTURE_2D
           0,                       //0 for now
           GL_RGB,                  //format opengl uses to read textures
           image[0]->sizeX,         //width
           image[0]->sizeY,         //height
           0,                       //the border of the image
           GL_RGB,                  //GL_RGB because pixels are stored in RGB format
           GL_UNSIGNED_BYTE,        //GL_UNSIGNED_BYTE because pixels are stored as unsigned numbers
           image[0]->data);         //actual pixel data
}

void Model::Draw()
{
        glPushMatrix();
        glTranslatef(m_CenterX, m_CenterY, m_CenterZ);

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, m_Texture);

        glBegin(GL_TRIANGLES);
        //my code for drawing the model to the screen. it isn't the problem so i removed it
        glEnd();

        glDisable(GL_TEXTURE_2D);
        glPopMatrix();
}

Model model;
Model model1;

// Drawing routine.
void drawScene(void)
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   glLoadIdentity();

   model.SetCenterX(0);
   model.SetCenterY(0); 
   model.SetCenterZ(12);
   model.Draw();

   model1.SetCenterX(12);
   model1.SetCenterY(10);
   model1.SetCenterZ(0);
   model1.Draw();

   glutSwapBuffers();
}

void setup(void) 
{
    glClearColor(0.0, 0.0, 0.0, 0.0); 

    //model = Model("monkey.obj", "launch");
    model = Model("cube.obj", "launch");

    model1 = Model("cube.obj", "grass");

   // Specify how texture values combine with current surface color values.
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
}

提前谢谢你。

【问题讨论】:

  • 据我所知,您根本没有调用您的 drawscene 函数。
  • 另外,我没有看到你调用 glGenTexture() 来获取纹理 ID。
  • 强制性注释:您正在使用已弃用的固定功能管道(glBeginglEnd 等)。考虑迁移到带有着色器的更现代的 OpenGL。
  • @Bot 我没有发布我的整个代码,因为其余的不是必需的。问题出在我的纹理功能上。我省略了调用 setup、drawscene 和其余部分的 main
  • @vesan glGenTexture() 是如何工作的?在我把它移到一个类之前的原始代码中,在 setup 函数中有那个。您对此有何建议?我绝对想远离 glbegin/glen,因为我听说它们真的很糟糕。我尝试使用 glBindVertexArray(),但它给了我一个未处理的异常,我找不到解决方案。

标签: c++ opengl textures


【解决方案1】:

问题是您没有创建纹理 ID。您可以使用glGenTextures 函数来做到这一点。在您的情况下,我会将其放在 LoadTexture 方法的开头 - 只需向它询问 1 个纹理 ID,然后将它给您的内容保存回 m_Texture

请记住,就像您使用glGen* 创建的所有内容一样,当您使用glDelete*(在本例中为glDeleteTextures)完成它时,也应该将其删除。

另外,考虑迁移到带有着色器和顶点数组的更现代的 OpenGL。不幸的是,这是一个非常广泛的话题。有很多教程和书籍,我从OpenGL Superbible 学到的,虽然我听说有些人不太喜欢它...

【讨论】:

  • 感谢您的回答。这就是问题所在。我应该把删除代码放在哪里?
  • 我一直在寻找,但我无法理解它。如果我尝试调用 glGenVertexArrays 它会给我一个未处理的异常。知道这是为什么吗?
  • 我没有在您的代码中看到任何清理。通常,当您使用完特定资源(如模型或纹理)并想要释放内存时,您会调用 delete。考虑加载一个新关卡,如果您不再需要它,您可以从上一个关卡中删除内容。我真的建议阅读一些 VAO 教程。或者,如果您有特定问题,请发布新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
  • 2012-02-07
  • 2018-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多