Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 2 of 2

Thread: Trouble texture mapping an image on sphere.

  1. #1
    Junior Member Newbie
    Join Date
    Sep 2017
    Posts
    3

    Trouble texture mapping an image on sphere.

    Hey guys, I'm trying to texture map an image onto a sphere in OpenGL 3.3. But instead of showing the image it's showing something like this:
    Click image for larger version. 

Name:	Screenshot from 2017-10-31 11-25-04.jpg 
Views:	7 
Size:	6.4 KB 
ID:	2534
    I'm trying to map the face of buzz light year which is a 512x512 bmp image, and I don't know why it isn't texture mapping like it should on the sphere. It's coming out fine on a cube or any flat surface, but I'm having trouble mapping it to a sphere. Here's the code I'm using.
    Code :
    double Radius = 0.5;
    int Lat = 10;
    int Long = 10;
     
    glm::vec2 t_coords[4] = {
      glm::vec2( 0.0, 0.0),
      glm::vec2( 0.0, 1.0),
      glm::vec2( 1.0, 0.0),
      glm::vec2( 1.0, 1.0)
    };
    void sphere(double radius, int Lats, int Longs)
    {
      float lats,longs;
     
      float slices=(180/(float(Lats)*10))/2;
      float sectors=(180/(float(Longs)*10))/2;
     
      float l;int i=0;
     
      for (lats = 0.0; lats <= PI; lats+=sectors)  
      {
          for(longs = 0.0; longs <= 2.0*PI; longs+=slices)
    	{
    	  float x = radius * sin(lats) * cos(longs);
    	  float y = radius * sin(lats) * sin(longs);
    	  float z = radius * cos(lats);
    	  glm::vec4 pt(x, y, z, 1.0);
        if(i>3) i=0;
    	  v_colors[tri_idx] = white; v_positions[tri_idx] = pt; tex_coords[tri_idx] = t_coords[i];
    	  v_normals[tri_idx] = pt; tri_idx++; i++;
     
    	  w_colors[wire_idx] = black; w_positions[wire_idx] = pt; 
    	  w_normals[wire_idx] = pt; wire_idx++;
     
     
    	  if(lats+sectors>PI)
    	    l=PI;
    	  else
    	    l=lats+sectors;
    	  x = radius * sin(l) * cos(longs);
    	  y = radius * sin(l) * sin(longs);
    	  z = radius * cos(l);
    	  pt =glm::vec4(x, y, z, 1.0);
        if(i>3) i=0;
    	  v_colors[tri_idx] = white; v_positions[tri_idx] = pt; tex_coords[tri_idx] = t_coords[i];
    	  v_normals[tri_idx] = pt; tri_idx++; i++;
     
    	  w_colors[wire_idx] = black; w_positions[wire_idx] = pt; 
    	  w_normals[wire_idx] = pt; wire_idx++;
     
    	}
        }
      // To Complete the wireframe
      for (lats = 0.0; lats <= PI; lats+=sectors)  
        {
          for(longs = 0.0; longs <= 2.0*PI; longs+=slices)
    	{
    	  float x = radius * sin(lats) * cos(longs);
    	  float y = radius * sin(lats) * sin(longs);
    	  float z = radius * cos(lats);
    	  glm::vec4 pt(x, y, z, 1.0);
     
    	  w_colors[wire_idx] = black; w_positions[wire_idx] = pt; 
    	  w_normals[wire_idx] = pt; wire_idx++;
     
    	}
        }
    }
    void initBuffersGL(void)
    {
     
      // Load shaders and use the resulting shader program
      std::string vertex_shader_file("vshader.glsl");
      std::string fragment_shader_file("fshader.glsl");
     
      std::vector<GLuint> shaderList;
      shaderList.push_back(csX75::LoadShaderGL(GL_VERTEX_SHADER, vertex_shader_file));
      shaderList.push_back(csX75::LoadShaderGL(GL_FRAGMENT_SHADER, fragment_shader_file));
     
      shaderProgram = csX75::CreateProgramGL(shaderList);
      glUseProgram( shaderProgram );
     
      // getting the attributes from the shader program
      GLuint vPosition = glGetAttribLocation( shaderProgram, "vPosition" );
      GLuint vColor = glGetAttribLocation( shaderProgram, "vColor" ); 
      GLuint vNormal = glGetAttribLocation( shaderProgram, "vNormal" ); 
      GLuint texCoord = glGetAttribLocation( shaderProgram, "texCoord" ); 
      uModelViewMatrix = glGetUniformLocation( shaderProgram, "uModelViewMatrix");
      normalMatrix =  glGetUniformLocation( shaderProgram, "normalMatrix");
      viewMatrix = glGetUniformLocation( shaderProgram, "viewMatrix");
     
      // Load Textures 
      GLuint tex=LoadTexture("images/buzz_face.bmp",512,512);
      glBindTexture(GL_TEXTURE_2D, tex);
     
      //Ask GL for two Vertex Attribute Objects (vao) , one for the colorcube and one for the plane.
      glGenVertexArrays (2, vao);
      //Ask GL for two Vertex Buffer Object (vbo)
      glGenBuffers (2, vbo);
     
      //Set 0 as the current array to be used by binding it
      glBindVertexArray (vao[0]);
      //Set 0 as the current buffer to be used by binding it
      glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
     
      // Call the sphere function
      Lat = tesselation;
      Long = tesselation;
      sphere(Radius, Lat, Long);
     
      //Copy the points into the current buffer
      glBufferData (GL_ARRAY_BUFFER, sizeof (v_positions) + sizeof(v_colors) + sizeof(v_normals), NULL, GL_STATIC_DRAW);
      glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(v_positions), v_positions );
      glBufferSubData( GL_ARRAY_BUFFER, sizeof(v_positions), sizeof(v_colors), v_colors );
      glBufferSubData( GL_ARRAY_BUFFER, sizeof(v_colors)+sizeof(v_positions), sizeof(v_normals), v_normals );
      // set up vertex array
     
      glEnableVertexAttribArray( vPosition );
      glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
     
      //Textures
      glEnableVertexAttribArray( texCoord );
      glVertexAttribPointer( texCoord, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions)) );
     
      // glEnableVertexAttribArray( vColor );
      // glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions)) );
     
      // glEnableVertexAttribArray( vNormal );
      // glVertexAttribPointer( vNormal, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions) + sizeof(v_colors)) );
     
      //Normal
      glEnableVertexAttribArray( vNormal );
      glVertexAttribPointer( vNormal, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions)+sizeof(tex_coords)) );
     
      // For The Wireframe too ... --------
     
      //Set 1 as the current array to be used by binding it
      glBindVertexArray (vao[1]);
      //Set 1 as the current buffer to be used by binding it
      glBindBuffer (GL_ARRAY_BUFFER, vbo[1]);
     
        //Copy the points into the current buffer
      glBufferData (GL_ARRAY_BUFFER, sizeof (w_positions) + sizeof(w_colors) + sizeof(w_normals), NULL, GL_STATIC_DRAW);
      glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(w_positions), w_positions );
      glBufferSubData( GL_ARRAY_BUFFER, sizeof(w_positions), sizeof(w_colors), w_colors );
      glBufferSubData( GL_ARRAY_BUFFER, sizeof(w_colors)+sizeof(w_positions), sizeof(w_normals), w_normals );
     
      // set up vertex array
     
      glEnableVertexAttribArray( vPosition );
      glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
     
      glEnableVertexAttribArray( vColor );
      glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(w_positions)) );
     
      glEnableVertexAttribArray( vNormal );
      glVertexAttribPointer( vNormal, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(w_positions) + sizeof(w_colors)) );
     
     
    }
     
    GLuint LoadTexture( const char * filename, int width, int height )
    {
        GLuint texture;
        unsigned char header[54];// 54 Byte header of BMP
        int pos;
        unsigned int w,h;
        unsigned int size; //w*h*3
        unsigned char * data; // Data in RGB FORMAT
        FILE * file;
     
        file = fopen( filename, "rb" ); 
        if ( file == NULL ) return 0;  // if file is empty 
        if (fread(header,1,54,file)!=54)
          {
    	printf("Incorrect BMP file\n");
    	return 0;
          }
     
        // Read  MetaData
        pos = *(int*)&(header[0x0A]);
        size = *(int*)&(header[0x22]);
        w = *(int*)&(header[0x12]);
        h = *(int*)&(header[0x16]);
     
        //Just in case metadata is missing
        if(size == 0) 
          size = w*h*3;
        if(pos == 0)
          pos = 54;
     
        data = new unsigned char [size];
     
        fread( data, size, 1, file ); // read the file
        fclose( file );
        //////////////////////////
     
        glGenTextures( 1, &texture );
        glBindTexture( GL_TEXTURE_2D, texture );
     
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
     
     
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
     
        free( data );
        return texture;// return the texture id
    }

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,466
    Your texture coordinates are bogus. I don't know exactly how you intend to map the image to the sphere, but the texture coordinates should probably be based upon lat/lon.

    Also: note that some amount of distortion is unavoidable with the fixed-function pipeline. You'll end up with a grid of trapezoids, each of which will be split into two triangles. One of those triangles will be larger than the other, but both will map to the same area of the texture, resulting in a crease along the diagonal. You can avoid this issue by using a bilinear mapping, but that requires shaders; fixed-function texturing is limited to affine or projective mapping.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •