title: SDL 3d OpenGL: texture on cube produces blank screen
body: <p>I have been trying to load a texture on to a cube using SDL_image and OpenGL.  For some reason, the entire window remains blank when I attempt to use textures.  By commenting out my texture initialisation call, the window renders as it should, except with a white texture.  The same applies when my call to glEnable(GL_TEXTURE_2D) gets commented out.  I have been trying for several hours now to fix this, and have spent most of those looking online for whether anyone has come up with a solution, but nothing I tried worked.  I have posted only sections of my code below, if more is required, please let me know.</p>
  
  <p>OpenGL initialisation (The order for glEnable(GL_TEXTURE_2D) may be incorrect):</p>
  
  <pre><code>//Configures OpenGL for 3d rendering
  //Needs to know the window height and width
  void setUpOpenGL(int width, int height)
  {
  //Enable depth testing, necessary for 3d worlds
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_TEXTURE_2D);
  
  //Set the background colour to black
  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  //Set the clear depth at 1m?
  glClearDepth(1.0f);
  
  //Configure the viewport, giving height and width
  glViewport(0, 0, width, height);
  
  //Clear the colour buffer
  glClear(GL_COLOR_BUFFER_BIT);
  
  //Initiate OpenGL for projection drawing
  glMatrixMode(GL_PROJECTION);
  //Load identity, purpose still unknown
  glLoadIdentity();
  
  //Initiate viewport as perspective, give the field of view, aspect ratio (width/height), minimum distance and maximum distance
  gluPerspective(45.0f, (float)width / (float)height, 0.01f, 500.0f);
  
  //Initiate OpenGL for model drawing, preparation for frame rendering
  glMatrixMode(GL_MODELVIEW);
  //Load identity again (identity matrix?)
  glLoadIdentity();
  
  //Set the shading model to smooth.  Other options feasable, but don't look as good
  glShadeModel(GL_SMOOTH);
  //For whatever reason, we need to state how to calculate depth.  Grouped under "Alpha Function"
  glDepthFunc(GL_LEQUAL);
  
  //Calculate perspective as "nicest"; "don't care" and "fastest" are other options
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  
  //Finished configuring OpenGL
  return;
  }
  </code></pre>
  
  <p>Here my loadTexture function (errorCode remains 0 through the entire function, and nothing is printed to stderr):</p>
  
  <pre><code>//Function to load textures from file.  Needs to know the filename / relative location.
  //Load textures from file
  int loadTexture(char *filename)
  {
  GLuint returnValue = -1;
  SDL_Surface *image;
  void *raw;
  int width, height, bpp;
  Uint8 *srcPixel, *dstPixel;
  Uint32 truePixel;
  GLenum errorCode;
  
  image = IMG_Load(filename);
  
  if(!image)
  {
      fprintf(stderr, "Warning: Error loading image %s: %s\n", filename, IMG_GetError());
      return -2;
  }
  
  if(image-&gt;format-&gt;BytesPerPixel &lt; 2)
  {
      fprintf(stderr, "Warning: %s is a bad image, not true colour\n", filename);
      return -3;
  }
  
  width = image-&gt;w;
  height = image-&gt;h;
  
  raw = (void *)malloc(width * height * 4);
  dstPixel = (Uint8 *)raw;
  
  SDL_LockSurface(image);
  
  bpp = image-&gt;format-&gt;BytesPerPixel;
  
  for(int i = height - 1; i &gt;= 0; i--)
  {
      for(int j = 0; j &lt; width; j++)
      {
          srcPixel = (Uint8 *)image-&gt;pixels + i * image-&gt;pitch + j * bpp;
  
          switch(bpp)
          {
          case 1:
              truePixel = *srcPixel;
              break;
          case 2:
              truePixel = *(Uint16 *)srcPixel;
              break;
          case 3:
              if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
                  truePixel = srcPixel[0] &lt;&lt; 16 | srcPixel[1] &lt;&lt; 8 | srcPixel[2];
              else
                  truePixel = srcPixel[0] | srcPixel[1] &lt;&lt; 8 | srcPixel[2] &lt;&lt; 16;
              break;
          case 4:
              truePixel = *(Uint32 *)srcPixel;
              break;
          default:
              fprintf(stderr, "Warning: image BPP of %d in image %s unuseable\n", bpp, filename);
              SDL_UnlockSurface(image);
              SDL_FreeSurface(image);
              free(raw);
              return -4;
          }
  
          SDL_GetRGBA(truePixel, image-&gt;format, &amp;(dstPixel[0]), &amp;(dstPixel[1]), &amp;(dstPixel[2]), &amp;(dstPixel[3]));
          dstPixel++;
          dstPixel++;
          dstPixel++;
          dstPixel++;
      }
  }
  
  SDL_UnlockSurface(image);
  SDL_FreeSurface(image);
  
  while(glGetError());
  
  glGenTextures(1, &amp;returnValue);
  glBindTexture(GL_TEXTURE_2D, returnValue);
  
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_LINEAR*/);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  //glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
  
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  
  glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (Uint8 *)raw);
  
  errorCode = glGetError();
  if(errorCode)
  {
      if(errorCode == GL_OUT_OF_MEMORY)
          fprintf(stderr, "Warning: Texture memory full while binding texture from image %s\n", filename);
      else
          fprintf(stderr, "OpenGL error while creating texture: %d", (int)errorCode);
  
      glDeleteTextures(1, &amp;returnValue);
      free(raw);
      return -5;
  }
  
  //gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (Uint8 *)raw);
  
  errorCode = glGetError();
  if(errorCode)
  {
      if(errorCode == GL_OUT_OF_MEMORY)
          fprintf(stderr, "Warning: Texture memory full while building texture from image %s\n", filename);
      else
          fprintf(stderr, "OpenGL error while creating texture: %s", (int)errorCode);
  
      glDeleteTextures(1, &amp;returnValue);
      free(raw);
      return -6;
  }
  
  return returnValue;
  }
  </code></pre>
  
  <p>Finally, my actual render code.  Note that the return value for the loadTexture function is copied into all elements of the texture array (right, left, top, bottom, front, back (enums)).</p>
  
  <pre><code>void cube::render(void)
  {
  float xMinOffset, xMaxOffset, yMinOffset, yMaxOffset, zMinOffset, zMaxOffset;
  //getoffset(xMinOffset, xMaxOffset, yMinOffset, yMaxOffset, zMinOffset, zMaxOffset);
  
  xMinOffset = yMinOffset = zMinOffset = 0.0f;
  xMaxOffset = yMaxOffset = zMaxOffset = 1.0f;
  
  //Positive x, or right
  glBegin(GL_QUADS);
  {
      glColor3f(1.0f, 1.0f, 1.0f);
      glNormal3f(1.0f, 0.0f, 0.0f);
      glBindTexture(GL_TEXTURE_2D, texture[right]);
  
      glTexCoord2f(0.0f, 1.0f);
      glVertex3f(xMaxOffset, yMinOffset, zMinOffset);
      glTexCoord2f(1.0f, 1.0f);
      glVertex3f(xMaxOffset, yMinOffset, zMaxOffset);
      glTexCoord2f(1.0f, 0.0f);
      glVertex3f(xMaxOffset, yMaxOffset, zMaxOffset);
      glTexCoord2f(0.0f, 0.0f);
      glVertex3f(xMaxOffset, yMaxOffset, zMinOffset);
  }
  glEnd();
  
  //Negative x, or left
  glBegin(GL_QUADS);
  {
      glColor3f(1.0f, 1.0f, 1.0f);
      glNormal3f(-1.0f, 0.0f, 0.0f);
      glBindTexture(GL_TEXTURE_2D, texture[left]);
  
      glTexCoord2f(0.0f, 1.0f);
      glVertex3f(xMinOffset, yMinOffset, zMinOffset);
      glTexCoord2f(1.0f, 1.0f);
      glVertex3f(xMinOffset, yMinOffset, zMaxOffset);
      glTexCoord2f(1.0f, 0.0f);
      glVertex3f(xMinOffset, yMaxOffset, zMaxOffset);
      glTexCoord2f(0.0f, 0.0f);
      glVertex3f(xMinOffset, yMaxOffset, zMinOffset);
  }
  glEnd();
  
  //Positive y, or top
  glBegin(GL_QUADS);
  {
      glColor3f(1.0f, 1.0f, 1.0f);
      glNormal3f(0.0f, 1.0f, 0.0f);
      glBindTexture(GL_TEXTURE_2D, texture[top]);
  
      glTexCoord2f(1.0f, 1.0f);
      glVertex3f(xMinOffset, yMaxOffset, zMinOffset);
      glTexCoord2f(1.0f, 0.0f);
      glVertex3f(xMinOffset, yMaxOffset, zMaxOffset);
      glTexCoord2f(0.0f, 0.0f);
      glVertex3f(xMaxOffset, yMaxOffset, zMaxOffset);
      glTexCoord2f(0.0f, 1.0f);
      glVertex3f(xMaxOffset, yMaxOffset, zMinOffset);
  }
  glEnd();
  
  //Negative y, or bottom
  glBegin(GL_QUADS);
  {
      glColor3f(1.0f, 1.0f, 1.0f);
      glNormal3f(0.0f, -1.0f, 0.0f);
      glBindTexture(GL_TEXTURE_2D, texture[bottom]);
  
      glTexCoord2f(1.0f, 1.0f);
      glVertex3f(xMinOffset, yMinOffset, zMinOffset);
      glTexCoord2f(1.0f, 0.0f);
      glVertex3f(xMinOffset, yMinOffset, zMaxOffset);
      glTexCoord2f(0.0f, 0.0f);
      glVertex3f(xMaxOffset, yMinOffset, zMaxOffset);
      glTexCoord2f(0.0f, 1.0f);
      glVertex3f(xMaxOffset, yMinOffset, zMinOffset);
  }
  glEnd();
  
  //Positive z, or front
  glBegin(GL_QUADS);
  {
      glColor3f(1.0f, 1.0f, 1.0f);
      glNormal3f(0.0f, 0.0f, 1.0f);
      glBindTexture(GL_TEXTURE_2D, texture[front]);
  
      glTexCoord2f(0.0f, 1.0f);
      glVertex3f(xMinOffset, yMinOffset, zMaxOffset);
      glTexCoord2f(0.0f, 0.0f);
      glVertex3f(xMinOffset, yMaxOffset, zMaxOffset);
      glTexCoord2f(1.0f, 0.0f);
      glVertex3f(xMaxOffset, yMaxOffset, zMaxOffset);
      glTexCoord2f(1.0f, 1.0f);
      glVertex3f(xMaxOffset, yMinOffset, zMaxOffset);
  }
  glEnd();
  
  //Negative z, or back
  glBegin(GL_QUADS);
  {
      glColor3f(1.0f, 1.0f, 1.0f);
      glNormal3f(0.0f, 0.0f, -1.0f);
      glBindTexture(GL_TEXTURE_2D, texture[back]);
  
      glTexCoord2f(1.0f, 1.0f);
      glVertex3f(xMinOffset, yMinOffset, zMinOffset);
      glTexCoord2f(1.0f, 0.0f);
      glVertex3f(xMinOffset, yMaxOffset, zMinOffset);
      glTexCoord2f(0.0f, 0.0f);
      glVertex3f(xMaxOffset, yMaxOffset, zMinOffset);
      glTexCoord2f(0.0f, 1.0f);
      glVertex3f(xMaxOffset, yMinOffset, zMinOffset);
  }
  glEnd();
  }
  </code></pre>
  
  <p>And here the render function, along with some other drawing-related functions.  Note that initDisplayLists() is called in initialisation.</p>
  
  <pre><code>void redraw(void)
  {
  //Still has the data from the previous frame
  //Clear the colour and depth buffers before rendering
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  //Load identity, purpose unknown
  glLoadIdentity();
  
  //Draw horizontal crosshair
  glBegin(GL_LINES);
  {
      //White colour
      glColor3f(1.0f, 1.0f, 1.0f);
      //x, y, z
      //Vertex2f would be ideal, but doesn't appear (min view distance for perspective?)
      glVertex3f(-0.0001f, 0.0f, -0.01f);
      glVertex3f(0.0001f, 0.0f, -0.01f);
  }
  glEnd();
  //Draw vertical crosshair
  glBegin(GL_LINES);
  {
      //Also white
      glColor3f(1.0f, 1.0f, 1.0f);
      //Again: x, y, z
      glVertex3f(0.0f, -0.0001f, -0.01f);
      glVertex3f(0.0f, 0.0001f, -0.01f);
  }
  glEnd();
  
  //Rotate on the x axis (pitch)
  glRotatef(se::pl0.rX, 1.0f, 0.0f, 0.0f);
  //Rotate viewport on the y axis (yaw)
  glRotatef(se::pl0.rY, 0.0f, 1.0f, 0.0f);
  //Translate the world by the negative of our coordinates
  //Camera one way = objects the other...
  glTranslatef(-se::pl0.x, -se::pl0.y, -se::pl0.z);
  
  glCallList(1);
  
  //Show the screen we have been calculating, preparing the screen we were showing for drawing
  SDL_GL_SwapBuffers();
  return;
  }
  
  void initDisplayLists(void)
  {
  glGenLists(1);
  
  cube block = cube();
  
  glNewList(1, GL_COMPILE);
  {
      block.render();
  }
  glEndList();
  
  return;
  }
  </code></pre>