【问题标题】:How to apply textures to a quad in order to texture a cube?如何将纹理应用到四边形以纹理立方体?
【发布时间】:2010-07-17 11:34:40
【问题描述】:

最近我一直在研究 OpenGL,如果我想对事物进行纹理处理,我已经上台了。我想我会从纹理一个简单的立方体开始。 我目前有这段代码,并且完全理解它是如何工作的:

#include <glut.h>

#define WINDOW_WIDTH 400
#define WINDOW_HEIGHT 400


float angle = 30.0f;

void Draw() {

  glLoadIdentity(); //Reset the drawing perspective
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clears the buffers

  //Add positioned light
  GLfloat lightColor0[] = {0.5f, 0.5f, 0.5f, 1.0f}; //Color intensity
  GLfloat lightPos0[] = {0.0f, 0.0f, 0.0f, 1.0f}; //Positioned at..
  glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0); //Set our light colour
  glLightfv(GL_LIGHT0, GL_POSITION, lightPos0); //Set our light position

  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 200);

  glRotatef(angle,1.0f,1.0f,1.0f); //Rotate around the origin
  glScalef(0.4f, 0.4f, 0.4f); //Scale the shape down
  glBegin(GL_QUADS); //Start drawing a Quad
  glColor3f(1.0f,0.0f,0.0f); //Set the colour to Red
  glVertex3f( 1.0f, 1.0f,-1.0f); //Top right of the quad (Top Face)
  glVertex3f(-1.0f, 1.0f,-1.0f); //Top left of the quad (Top Face)
  glVertex3f(-1.0f, 1.0f, 1.0f); //Bottom left of the quad (Top Face)
  glVertex3f( 1.0f, 1.0f, 1.0f); //Bottom right of the quad (Top Face)
  glVertex3f( 1.0f,-1.0f, 1.0f); //Top right of the quad (Bottom Face)
  glVertex3f(-1.0f,-1.0f, 1.0f); //Top left of the quad (Bottom Face)
  glVertex3f(-1.0f,-1.0f,-1.0f); //Bottom left of the quad (Bottom Face)
  glVertex3f( 1.0f,-1.0f,-1.0f); //Bottom right of the quad (Bottom Face)
  glVertex3f( 1.0f, 1.0f, 1.0f); //Top right of the quad (Front Face)
  glVertex3f(-1.0f, 1.0f, 1.0f); //Top left of the quad (Front Face)
  glVertex3f(-1.0f,-1.0f, 1.0f); //Bottom left of the quad (Front Face)
  glVertex3f( 1.0f,-1.0f, 1.0f); //Bottom right of the quad (Front Face)
  glVertex3f( 1.0f,-1.0f,-1.0f); //Top right of the quad (Back Face)
  glVertex3f(-1.0f,-1.0f,-1.0f); //Top left of the quad (Back Face)
  glVertex3f(-1.0f, 1.0f,-1.0f); //Bottom left of the quad (Back Face)
  glVertex3f( 1.0f, 1.0f,-1.0f); //Bottom right of the quad (Back Face)
  glVertex3f(-1.0f, 1.0f, 1.0f); //Top right of the quad (Left Face)
  glVertex3f(-1.0f, 1.0f,-1.0f); //Top left of the quad (Left Face)
  glVertex3f(-1.0f,-1.0f,-1.0f); //Bottom left of the quad (Left Face)
  glVertex3f(-1.0f,-1.0f, 1.0f); //Bottom right of the quad (Left Face)
  glVertex3f( 1.0f, 1.0f,-1.0f); //Top right of the quad (Right Face)
  glVertex3f( 1.0f, 1.0f, 1.0f); //Top left of the quad (Right Face)
  glVertex3f( 1.0f,-1.0f, 1.0f); //Bottom left of the quad (Right Face)
  glVertex3f( 1.0f,-1.0f,-1.0f); //Bottom right of the quad (Right Face)
  glEnd(); //Finished Drawing The Quad
  glutSwapBuffers(); //Send the 3D scene to the screen
}

void Update(int value){ //Our update function
  angle+=0.5f; //Increase the angle by 5

  if(angle>360){ //If the angle is greater than 360
    angle=0; //Set the angle to 0
  }

  glutPostRedisplay(); //Tell it that the scene has changed
  glutTimerFunc(25,Update,0); //Call "Update" again in another 25ms
}

void Initialize() {
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_COLOR_MATERIAL);
  glEnable(GL_LIGHTING); //Enable lighting
  glEnable(GL_LIGHT0); //Enable light No. 0
  glEnable(GL_NORMALIZE); //Automatically "normalize" normals
  glShadeModel(GL_SMOOTH); //Enable smooth shading (nice effect)  

  glClearColor(0.0, 0.0, 0.0, 0.0); //Background RGBA
  glMatrixMode(GL_MODELVIEW); //MODELVIEW view
  glLoadIdentity(); //Start at origin
  glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); //Set the scale
  //X axis = 0 to 1. Y = 0 to 1. Z = -1 to 1.
}

int main() {
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); //The display mode
  glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); //Window Size
  glutInitWindowPosition(200, 200); //Window Position
  glutCreateWindow("Lighting!"); //Creates a window with the name "Lighting!"
  Initialize(); //Call our initialize function.
  glutDisplayFunc(Draw); //"Draw" then refresh the window
  glutTimerFunc(25,Update,0); //Call "Update" 25ms after program starts
  glutMainLoop(); //Process events etc. Also keeps the window open.
  return 0; //End the program
}

然而,在阅读了很多很多纹理教程之后(我的意思是我可以在网上找到的所有教程);我仍然对如何将其添加到该程序中感到困惑。 我知道我必须(以某种方式)加载纹理,然后在绘制立方体之前使用 glBindTexture 函数绑定它,但我认为在这两者之间我还需要做一些其他事情(而且我不知道如何加载图像也正确)。

【问题讨论】:

    标签: c++ opengl textures cube


    【解决方案1】:

    要加载纹理文件(png、jpg...),请使用以下命令: (别忘了安装 SDL 和 SDL_image 库)

    #include <SDL/SDL.h>
    #include <SDL/SDL_image.h>
    
    GLuint texture_alloc(const char  *tex_name, int alpha)
    {
        GLuint tex_num;
    
        SDL_Surface *tex_img;
        glGenTextures(1, &tex_num);
    
        if(tex_img = (SDL_Surface *) IMG_Load(tex_name)) {
    
            glBindTexture(GL_TEXTURE_2D, tex_num);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
    
            if (alpha==1)
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_img->w, tex_img->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_img->pixels);
            else
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_img->w, tex_img->h, 0, GL_RGB, GL_UNSIGNED_BYTE, tex_img->pixels);
            SDL_FreeSurface (tex_img);
        }
    
        return tex_num;
    
    }
    

    使用 glTexCoord 函数设置纹理坐标:

    glTexCoord2f(0.0f, 0.0f);
    glVertex3f( 1.0f, 1.0f,-1.0f); 
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(-1.0f, 1.0f,-1.0f);
    .
    .
    .
    

    【讨论】:

    • + 你可以将 (alpha==1) 替换为 (tex_img->format->BitsPerPixel==32) /RGBA/
    【解决方案2】:

    我建议查看SOIL,一个 OpenGL 图像加载库 - 我使用它。

    就纹理的工作而言,它几乎是:

    Unsigned int texture = SOIL_load_OGL_texture(imagePath.c_str(), SOIL_CREATE_NEW_ID, SOIL_LOAD_AUTO, SOIL_FLAG_MIPMAPS);
    
    glBindTexture(texture);
    

    但是,您必须使用纹理坐标,以便 opengl 知道如何包装您的纹理。下面是一些渲染立方体的示例调用。

        int size = 1;
    
        // Begin Rending
        glBegin(GL_QUADS);
    
        {
            // Face 1
    
            glNormal3f( 0.0f, 0.0f, 1.0f);  
    
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f( m_size, m_size,-m_size);
    
            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(-m_size, m_size,-m_size);
    
            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(-m_size, m_size, m_size);
    
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f( m_size, m_size, m_size);    
    
            // Face 2
    
            glNormal3f( 0.0f, 0.0f,-1.0f);
    
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f( m_size,-m_size, m_size);    
    
            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(-m_size,-m_size, m_size);
    
            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(-m_size,-m_size,-m_size);
    
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f( m_size,-m_size,-m_size);
    
            // Face 3
    
    
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f( m_size, m_size, m_size);    
    
            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(-m_size, m_size, m_size);
    
            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(-m_size,-m_size, m_size);    
    
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f( m_size,-m_size, m_size);
    
            // Face 4
    
            glNormal3f( 0.0f,-1.0f, 0.0f);  
    
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f( m_size,-m_size,-m_size);
    
            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(-m_size,-m_size,-m_size);
    
            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(-m_size, m_size,-m_size);
    
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f( m_size, m_size,-m_size);
    
            // Face 5
    
            glNormal3f( 1.0f, 0.0f, 0.0f);
    
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f(-m_size, m_size, m_size);    
    
            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(-m_size, m_size,-m_size);    
    
            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(-m_size,-m_size,-m_size);
    
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f(-m_size,-m_size, m_size);
    
            // Face 6
    
            glNormal3f( 1.0f, 0.0f, 0.0f);
    
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f( m_size, m_size,-m_size);
    
            glTexCoord2f(1.0f, 0.0f);
            glVertex3f( m_size, m_size, m_size);
    
            glTexCoord2f(1.0f, 1.0f);
            glVertex3f( m_size,-m_size, m_size);
    
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f( m_size,-m_size,-m_size);    
        }
    
        glEnd();
    

    【讨论】:

      【解决方案3】:

      我认为您缺少的部分是纹理坐标的概念。

      纹理是二维的吧?因此,当您将对象的 3d 点推送到图形卡时,如果您希望它具有纹理,您还需要将该 3d 点与纹理图像中的位置相关联,您可以使用一对纹理坐标(配对因为纹理是 2d)... 看看 glTexCoord2f()... 如果您在调用 glVertex3f() 之前调用它,您会将该 3d 点与图像中的一个点相关联... 如果您对构成原始 opengl 的所有点执行此操作,可以对中间的所有点进行插值...

      【讨论】:

      • 所以我必须创建立方体(使用我程序中已有的绘制代码),然后使用我的 Tomas Cokis 帖子中的大部分代码映射纹理?
      • 是的。您创建一个纹理,将图像加载到其中(我认为使用 glTexSubImage2d()),然后使用 glBindTexture() 以便openGL知道您在谈论什么纹理,然后当您推动几何图形时,您也会推动纹理坐标(使用glTexCoord2f()).
      • 好的,我想我明白了。但是您说要使用 hlTexSubImage2d() 加载图像,但是根据快速搜索,该函数没有文件路径参数;那么我如何实际加载图像? (我知道我可以使用 SOIL,但我通常不喜欢额外的预先创建的标头,如果可能的话,我更愿意以纯 OpenGL 的方式进行)。
      • 是的,glTexSubImage2d() 不知道图像文件...您必须为其提供指向充满像素的缓冲区的指针...
      • OpenGL 对文件一无所知。
      【解决方案4】:

      对于图像加载,您还可以使用 SDL 图像库:

      http://www.libsdl.org/projects/SDL_image/

      非常方便。

      【讨论】:

      • 我认为该库仅用于 SDL 的内置渲染?
      • 不,它是你想要的任何东西的扩展,当然,它可能需要 sdl(我不知道)但你可以在任何地方使用它
      【解决方案5】:

      您可以使用http://nehe.gamedeve.net/ 中的 glaux 代码,这也很简单。

      AUX_RGBImageRec* LoadBMP(char* Filename)
      {
          FILE *File = NULL;
      
          if ( !Filename )
              return NULL;
      
          File = fopen(Filename,"r");
      
          if ( !Filename )
              return NULL;
      
          fclose(File);
          return auxDIBImageLoad(Filename);
      }
      
      int LoadTextures()
      {
          int Status = FALSE;
          AUX_RGBImageRec *TextureImage[1];
          memset(TextureImage,0,sizeof(void*)*1);
      
          if ( TextureImage[0] = LoadBMP("GoneFishing.bmp") )
          {
              Status = true;
              if(texture[0] == -1)
                  glGenTextures(1,&texture[0]);
              glBindTexture(GL_TEXTURE_2D,texture[0]);
              // Generate The Texture
              glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
          }
      
          if (TextureImage[0])                            // If Texture Exists
          {
              if (TextureImage[0]->data)                  // If Texture Image Exists
              {
                  free(TextureImage[0]->data);                // Free The Texture Image Memory
              }
      
              free(TextureImage[0]);                      // Free The Image Structure
          }
      
          return Status;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-06
        • 1970-01-01
        • 1970-01-01
        • 2019-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多