/* checker.c texture mapping with a checkerboard pattern */
#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>

/* create checkerboard texture - some random patterns useful also */
/* size of 2D texture  row major */
#define checkerImageHeight 64 /* 32 makes 4x4 */
#define checkerImageWidth 64  /* 32 makes 4x4 */
#define alpha 128 /* transparent 0..255 opaque */
static GLubyte checkerImage[checkerImageHeight][checkerImageWidth][4];
static GLuint texName;
#define checkerImageHeight2 32 /* 32 makes 4x4 */
#define checkerImageWidth2 32  /* 32 makes 4x4 */
static GLubyte checkerImage2[checkerImageHeight2][checkerImageWidth2][4];
static GLuint texName2;

void makeCheckerImage(void)
{
  int i, j, c;
  
  for(i=0; i<checkerImageHeight; i++)
  {
    for(j=0; j<checkerImageWidth; j++)
    {
      c = ((((i&0x8)==0)^((j&0x8))==0))*255;
      checkerImage[i][j][0] = c; /* R 0..255 red checker */
      checkerImage[i][j][1] = 0; /* G 0..255 */
      checkerImage[i][j][2] = 0; /* B 0..255 */
      checkerImage[i][j][3] = alpha; /* A */
    }
  }
  for(i=0; i<checkerImageHeight2; i++)
  {
    for(j=0; j<checkerImageWidth2; j++)
    {
      c = ((((i&0x8)==0)^((j&0x8))==0))*255;
      checkerImage2[i][j][0] = 0; /* R 0..255 */
      checkerImage2[i][j][1] = c; /* G 0..255 green checker */
      checkerImage2[i][j][2] = 0; /* B 0..255 */
      checkerImage2[i][j][3] = alpha; /* A */
    }
  }
} /* end makeCheckerImage */

void init(void)
{
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glShadeModel(GL_FLAT);
  glEnable(GL_DEPTH_TEST);
  
  makeCheckerImage();
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  
  glGenTextures(1, &texName);
  glBindTexture(GL_TEXTURE_2D, texName);
  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, 0, GL_RGBA, checkerImageWidth,
               checkerImageHeight, 0, GL_RGBA,
               GL_UNSIGNED_BYTE, checkerImage);
  glGenTextures(2, &texName2);
  glBindTexture(GL_TEXTURE_2D, texName2);
  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, 0, GL_RGBA, checkerImageWidth2,
               checkerImageHeight2, 0, GL_RGBA,
               GL_UNSIGNED_BYTE, checkerImage2);
}

void display(void)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glEnable(GL_TEXTURE_2D);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  glBindTexture(GL_TEXTURE_2D, texName);
  glBegin(GL_QUADS);
    glColor3f(1.0, 0.0, 0.0);
    glTexCoord2f(0.0, 0.0);
    glVertex3f(-2.0, -1.0, 0.0);
    glTexCoord2f(0.0, 1.0);
    glVertex3f(-2.0,  1.0, 0.0);
    glTexCoord2f(1.0, 1.0);
    glVertex3f( 0.0,  1.0, 0.0);
    glTexCoord2f(1.0, 0.0);
    glVertex3f( 0.0, -1.0, 0.0);
  glEnd();

  glBindTexture(GL_TEXTURE_2D, texName2);
  glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0);
    glVertex3f( 1.0,     -1.0, 0.0);
    glTexCoord2f(0.0, 1.0);
    glVertex3f( 1.0,      1.0, 0.0);
    glTexCoord2f(1.0, 1.0);
    glVertex3f( 2.41421,  1.0, -1.41421);
    glTexCoord2f(1.0, 0.0);
    glVertex3f( 2.41421, -1.0, -1.41421);   
  glEnd();
  glFlush();
  glDisable(GL_TEXTURE_2D);
}

void reshape(int w, int h)
{
  glViewport(0, 0, (GLsizei)w, (GLsizei)h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 1.0, 30.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef(0.0, 0.0, -3.6);
}

void keyboard(unsigned char key, int x, int y)
{
  exit(0);
}

int main(int argc, char* argv[])
{
  /* which OpenGL am I using? */
  const GLubyte *info;
  
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(250, 250);
  glutInitWindowPosition(100, 100);
  glutCreateWindow(argv[0]);
  info = glGetString(GL_VENDOR); /* just demo, must follow 'create' */
  printf("vendor=%s\n", info);
  info = glGetString(GL_RENDERER);
  printf("renderer=%s\n", info);
  info = glGetString(GL_VERSION);
  printf("version=%s\n", info);
  info = glGetString(GL_EXTENSIONS);
  printf("extensions=%s\n", info);
  
  init();
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  glutKeyboardFunc(keyboard);
  glutMainLoop();
  return 0;
}

