2015-01-21 76 views
0

我試圖將我的代碼移到現代Opengl,但遇到了麻煩。現在我的代碼會繪製一個立方體,它會放置一個紋理,但它只會將第一個紋理附加到我的全部面部。我也使用SOIL將我的紋理加載到我的程序中。我究竟做錯了什麼?如何繪製具有不同紋理的所有面的立方體?

這是我的代碼:

class Rectangle 
{ 
public: 
    Rectangle(); 

    Rectangle(float x, float y, float z, float width, float height, float depth, string frontFace, string backFace, string leftFace, 
      string RightFace, string topFace, string bottomFace); 

    void Draw(); 
private: 
    GLuint m_Textures[6]; 
    string m_TextureNames[6]; 


    GLfloat m_Vertices[72]; // v0,v1,v2,v3 (front) 
    // normal array 
    GLfloat m_Normals[72]; // v0,v1,v2,v3 (front) 
    // color array 
    GLfloat m_Colours[72]; // v0,v1,v2,v3 (front) 
    // index array of vertex array for glDrawElements() & glDrawRangeElement() 
    GLubyte m_Indices[36];  // front 

    GLfloat m_Texcoords[48]; 
}; 

Rectangle::Rectangle(float x, float y, float z, float width, float height, float depth, string topFace, string bottomFace, string frontFace, 
      string backFace, string leftFace, string rightFace) 
{ 
    m_CenterX = x; 
    m_CenterY = y; 
    m_CenterZ = z; 
    m_Width = width; 
    m_Height = height; 
    m_Depth = depth; 

    m_TextureNames[0] = topFace; 
    m_TextureNames[1] = bottomFace; 
    m_TextureNames[2] = frontFace; 
    m_TextureNames[3] = backFace; 
    m_TextureNames[4] = leftFace; 
    m_TextureNames[5] = rightFace; 
    m_ObjectType = Textured; 

    GLfloat tempVert[] = { // front 
    -1.0, -1.0, 1.0, 
    1.0, -1.0, 1.0, 
    1.0, 1.0, 1.0, 
    -1.0, 1.0, 1.0, 
    // top 
    -1.0, 1.0, 1.0, 
    1.0, 1.0, 1.0, 
    1.0, 1.0, -1.0, 
    -1.0, 1.0, -1.0, 
    // back 
    1.0, -1.0, -1.0, 
    -1.0, -1.0, -1.0, 
    -1.0, 1.0, -1.0, 
    1.0, 1.0, -1.0, 
    // bottom 
    -1.0, -1.0, -1.0, 
    1.0, -1.0, -1.0, 
    1.0, -1.0, 1.0, 
    -1.0, -1.0, 1.0, 
    // left 
    -1.0, -1.0, -1.0, 
    -1.0, -1.0, 1.0, 
    -1.0, 1.0, 1.0, 
    -1.0, 1.0, -1.0, 
    // right 
    1.0, -1.0, 1.0, 
    1.0, -1.0, -1.0, 
    1.0, 1.0, -1.0, 
    1.0, 1.0, 1.0, 
    }; 

    // normal array 
    GLfloat tempNormals[] = { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0,v1,v2,v3 (front) 
          1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0,v3,v4,v5 (right) 
          0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0,v5,v6,v1 (top) 
          -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1,v6,v7,v2 (left) 
          0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // v7,v4,v3,v2 (bottom) 
          0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 }; // v4,v7,v6,v5 (back) 

    // color array 
    GLfloat tempColors[] = { 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, // v0,v1,v2,v3 (front) 
          1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, // v0,v3,v4,v5 (right) 
          1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, // v0,v5,v6,v1 (top) 
          1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, // v1,v6,v7,v2 (left) 
          0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // v7,v4,v3,v2 (bottom) 
          0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1 }; // v4,v7,v6,v5 (back) 

    // index array of vertex array for glDrawElements() & glDrawRangeElement() 
    GLubyte tempIndices[] = { 0, 1, 2, 2, 3, 0,  // front 
          4, 5, 6, 6, 7, 4,  // right 
          8, 9,10, 10,11, 8,  // top 
          12,13,14, 14,15,12,  // left 
          16,17,18, 18,19,16,  // bottom 
          20,21,22, 22,23,20 }; // back 

    GLfloat tempTexcoords[2*4*6] = { 
    // front 
    0.0, 0.0, 
    1.0, 0.0, 
    1.0, 1.0, 
    0.0, 1.0, 
    }; 
    for (int i = 1; i < 6; i++) 
    memcpy(&tempTexcoords[i*4*2], &tempTexcoords[0], 2*4*sizeof(GLfloat)); 


    copy(tempVert, tempVert + 72, m_Vertices); 
    copy(tempNormals, tempNormals + 72, m_Normals); 
    copy(tempColors, tempColors + 72, m_Colours); 

    copy(tempIndices, tempIndices + 36, m_Indices); 
    std::copy(tempTexcoords, tempTexcoords + 48, m_Texcoords); 

    LoadTexture(m_TextureNames); 
} 

void Rectangle::LoadTexture(string TextureName[6])   
{ 
    // Create texture index array. 
    glGenTextures(6, m_Textures); 


    for(int i = 0 ; i < 1 ; i++) 
    { 
     glBindTexture(GL_TEXTURE_2D, m_Textures[i]); 
     // Set our texture parameters 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
     // Set texture filtering 
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // NOTE the GL_NEAREST Here! 
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // NOTE the GL_NEAREST Here! 

     std::string fileType; 
     fileType.append(m_TextureNames[i], m_TextureNames[i].size()-3,3); 

     if(fileType == "jpg") 
     { 
      m_Textures[i] = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture 
      (
       m_TextureNames[i].c_str(), 
       SOIL_LOAD_AUTO, 
       SOIL_CREATE_NEW_ID, 
       SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT 
      ); 
      // allocate a texture name 
     } 
     else 
     { 
      m_Textures[i] = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture 
      (
       m_TextureNames[i].c_str(), 
       SOIL_LOAD_AUTO, 
       SOIL_CREATE_NEW_ID, 
       SOIL_FLAG_MIPMAPS | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT 
      ); 
      // allocate a texture name 
     } 

    } 
} 

// Function to draw Sphere. 
void Rectangle::Draw() 
{ 
     // enable and specify pointers to vertex arrays 
     glEnableClientState(GL_NORMAL_ARRAY); 
     glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
     glEnableClientState(GL_COLOR_ARRAY); 
     glEnableClientState(GL_VERTEX_ARRAY); 
     glNormalPointer(GL_FLOAT, 0, m_Normals); 
     glTexCoordPointer(2, GL_FLOAT, 0, m_Texcoords); 
     glColorPointer(3, GL_FLOAT, 0, m_Colours); 
     glVertexPointer(3, GL_FLOAT, 0, m_Vertices); 

     for (int i=0;i<6;i++) 
     { 
     glPushMatrix(); 
      glActiveTexture(GL_TEXTURE0); 
      glBindTexture(GL_TEXTURE_2D, m_Textures[i]); 

      glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, m_Indices); 
     glPopMatrix(); 
     } 

     glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays 
     glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
     glDisableClientState(GL_COLOR_ARRAY); 
     glDisableClientState(GL_NORMAL_ARRAY); 
} 


Rectangle testRect; 

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

    glLoadIdentity(); 

    testRect.Draw(); 

    glutSwapBuffers(); 
} 

// Initialization routine. 
void setup(void) 
{ 
    glClearColor(0.0, 0.0, 0.0, 0.0); 
    testRect = Rectangle(2, 0.0, 0.0, 1, 2, 1, "grass.bmp","grass.bmp", "grass.bmp", "launch.png", "launch.png", "launch.png"); 

    // Turn on OpenGL texturing. 
    glEnable(GL_TEXTURE_2D); 

    glShadeModel (GL_SMOOTH); 
} 

回答

2

張貼的代碼有幾個問題:

  • 它只加載一個紋理:

    glGenTextures(6, m_Textures); 
    
    for(int i = 0 ; i < 1 ; i++) 
    { 
        glBindTexture(GL_TEXTURE_2D, m_Textures[i]); 
        ... 
    

    如果要裝載6個紋理,如代碼的其餘部分建議,你將不得不使用6環的終值:

    for(int i = 0 ; i < 6 ; i++) 
    
  • 它是創造質感IDS兩次,並設置參數與錯誤的紋理綁定。在LoadTexture()開始時,它會產生6個質地IDS:

    glGenTextures(6, m_Textures); 
    

    ,然後結合它們,並且使glTexParameteri()設置對它們的各種參數。但隨後調用SOIL_load_ogl_texture()一個標誌要求它重新創建一個新的ID,然後存儲了一個遠:

    m_Textures[i] = SOIL_load_OGL_texture(
        m_TextureNames[i].c_str(), 
        SOIL_LOAD_AUTO, 
        SOIL_CREATE_NEW_ID, 
        SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT 
        ); 
    

    爲了解決這個問題,你可以省略gGenTextures()電話和移動代碼到紋理綁定撥SOIL_load_ogl_texture()後致電glTexParameteri()。此外,它使用標誌來生成mipmap,但設置紋理過濾器不使用mipmapping。

  • 在繪製函數,它循環通過6個面,但隨後每次繪製整個多維數據集:

    for (int i=0;i<6;i++) 
    { 
    glPushMatrix(); 
        glActiveTexture(GL_TEXTURE0); 
        glBindTexture(GL_TEXTURE_2D, m_Textures[i]); 
    
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, m_Indices); 
    glPopMatrix(); 
    } 
    

    的第二個參數glDrawElements()指定要呈現的頂點的數量。使用值36,將使用所有頂點(立方體的6邊,每個2個三角形,每個頂點3個頂點)

    此外,glPushMatrix()/glPopMatrix()絕對沒有用處。 :

    glActiveTexture(GL_TEXTURE0); 
    for (int i=0;i<6;i++) 
    { 
        glBindTexture(GL_TEXTURE_2D, m_Textures[i]); 
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, m_Indices + i * 6); 
    } 
    
  • 我沒有看到任何地方被啓用深度測試一下添加到setup()

    glEnable(GL_DEPTH_TEST); 
    
+0

我也想知道安博解決數組中元素數量和glDrawElements調用的問題。我沒有解決這個問題。我只討論瞭如何獲取加載和使用的紋理。 – jwlaughton 2015-01-21 04:12:33

+0

這讓它工作。謝謝!我仍然在努力學習如何使用現代的Opengl,但由於我找不到可用的教程,或者技術性太強,無法理解,所以我很難過。你提到的有一個mipmap的標誌。使用/標記mipmap是否很重要?我不完全瞭解SOIL庫,並且很難找到關於它的信息。 – WhyYouNoWork 2015-01-21 04:38:06

+0

解釋mipmapping超出了評論的範圍。應該有一些很好的教程,但我沒有具體的參考。你在這裏使用的大多數電話確實被棄用。 – 2015-01-21 04:41:25

0

我這樣做有點不同的作品,所以也許這個問題是不同。

我會將每個紋理綁定到不同的GL_Texture(GL_Texture0,GL_Texture1 ...),以便每個紋理都有它自己的數據。我不知道該怎麼土壤的作品,但在我來說,我的第一個紋理後:

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 

我將包括一個電話:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture1Width, texture1Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmapData); 

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, m_Textures[0]); 

而且我會重複此過程爲每個6紋理。

然後我想提請各面:

// First face 
glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, m_Textures[0]); 

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, m_Indices); 

// Second face 
glActiveTexture(GL_TEXTURE1); 
glBindTexture(GL_TEXTURE_2D, m_Textures[1]); 

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, m_Indices); 

等了每個面。

編輯:

我做了一些檢查有關土壤,它看起來對我來說,(使用土),你會:

GLuint m_Textures[6]; 
int img_width, img_height; 

glGenTextures(6, m_Textures); 

// For each texture 

unsigned char* img = SOIL_load_image(m_TextureNames[0].c_str(), &img_width, &img_height, NULL, 0); // or m_TextureNames[1].c_str() ... 

glBindTexture(GL_TEXTURE_2D, m_Textures[0]); // or m_textures[1]... 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
// Set texture filtering 
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // NOTE the GL_NEAREST Here! 
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // NOTE the GL_NEAREST Here! 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img_width, img_height, 0, GL_RGB, GL_UNSIGNED_BYTE, img); 

glActiveTexture(GL_TEXTURE0); // or GL_TEXTURE1.... 
glBindTexture(GL_TEXTURE_2D, m_Textures[0]); // or m_Textures[1]... 
相關問題