132001f49Smrg/**
232001f49Smrg * Test conversion of a perspective-interpolated value to be a linearly
332001f49Smrg * interpolated value.
432001f49Smrg * Brian Paul
532001f49Smrg * 22 March 2011
632001f49Smrg */
732001f49Smrg
832001f49Smrg
932001f49Smrg#include <assert.h>
1032001f49Smrg#include <string.h>
1132001f49Smrg#include <stdio.h>
1232001f49Smrg#include <stdlib.h>
1332001f49Smrg#include <math.h>
1432001f49Smrg#include <GL/glew.h>
1532001f49Smrg#include "glut_wrap.h"
1632001f49Smrg#include "shaderutil.h"
1732001f49Smrg
1832001f49Smrg
1932001f49Smrgstatic GLuint VertShader1, VertShader2;
2032001f49Smrgstatic GLuint FragShader1, FragShader2;
2132001f49Smrgstatic GLuint Program1, Program2;
2232001f49Smrgstatic GLint Win = 0;
2332001f49Smrgstatic int Width = 600, Height = 300;
2432001f49Smrg
2532001f49Smrg
2632001f49Smrgstatic void
2732001f49SmrgRedisplay(void)
2832001f49Smrg{
2932001f49Smrg   GLuint i;
3032001f49Smrg
3132001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3232001f49Smrg
3332001f49Smrg   /* draw left and right perspective projected quads */
3432001f49Smrg   for (i = 0; i < 2; i++) {
3532001f49Smrg      glPushMatrix();
3632001f49Smrg
3732001f49Smrg         if (i == 0) {
3832001f49Smrg            glUseProgram(Program1);
3932001f49Smrg            glViewport(0, 0, 300, 300);
4032001f49Smrg         }
4132001f49Smrg         else {
4232001f49Smrg            glUseProgram(Program2);
4332001f49Smrg            glViewport(300, 0, 300, 300);
4432001f49Smrg         }
4532001f49Smrg
4632001f49Smrg         glScalef(0.9, 0.9, 1.0);
4732001f49Smrg
4832001f49Smrg         glBegin(GL_POLYGON);
4932001f49Smrg         glTexCoord2f(0, 0);   glVertex3f(-1, -1, 0);
5032001f49Smrg         glTexCoord2f(1, 0);   glVertex3f( 1, -1, 0);
5132001f49Smrg         glTexCoord2f(1, 1);   glVertex3f( 1,  1, -12);
5232001f49Smrg         glTexCoord2f(0, 1);   glVertex3f(-1,  1, -12);
5332001f49Smrg         glEnd();
5432001f49Smrg
5532001f49Smrg      glPopMatrix();
5632001f49Smrg   }
5732001f49Smrg
5832001f49Smrg   /* draw grayscale quad in middle */
5932001f49Smrg   glUseProgram(0);
6032001f49Smrg   glViewport(0, 0, Width, Height);
6132001f49Smrg   glPushMatrix();
6232001f49Smrg      glTranslatef(0.0, -0.38, 0);
6332001f49Smrg      glScalef(0.05, 0.52, 1.0);
6432001f49Smrg      glBegin(GL_POLYGON);
6532001f49Smrg      glColor3f(0, 0, 0);   glVertex2f(-1, -1);
6632001f49Smrg      glColor3f(0, 0, 0);   glVertex2f( 1, -1);
6732001f49Smrg      glColor3f(1, 1, 1);   glVertex2f( 1,  1);
6832001f49Smrg      glColor3f(1, 1, 1);   glVertex2f(-1,  1);
6932001f49Smrg      glEnd();
7032001f49Smrg   glPopMatrix();
7132001f49Smrg
7232001f49Smrg   if (0) {
7332001f49Smrg      GLfloat buf1[300*4], buf2[300*4];
7432001f49Smrg      GLuint i;
7532001f49Smrg      glReadPixels(Width * 1 / 4, 0, 1, Height, GL_RGBA, GL_FLOAT, buf1);
7632001f49Smrg      glReadPixels(Width * 3 / 4, 0, 1, Height, GL_RGBA, GL_FLOAT, buf2);
7732001f49Smrg      for (i = 1; i < Height; i++) {
7832001f49Smrg         printf("row %d:  %f (delta %f)  %f (delta %f)\n",
7932001f49Smrg                i,
8032001f49Smrg                buf1[i*4], buf1[i*4] - buf1[i*4-4],
8132001f49Smrg                buf2[i*4], buf2[i*4] - buf2[i*4-4]);
8232001f49Smrg      }
8332001f49Smrg   }
8432001f49Smrg
8532001f49Smrg   glutSwapBuffers();
8632001f49Smrg}
8732001f49Smrg
8832001f49Smrg
8932001f49Smrgstatic void
9032001f49SmrgReshape(int width, int height)
9132001f49Smrg{
9232001f49Smrg   glViewport(0, 0, width, height);
9332001f49Smrg   glMatrixMode(GL_PROJECTION);
9432001f49Smrg   glLoadIdentity();
9532001f49Smrg   glFrustum(-1, 1, -1, 1, 2, 200);
9632001f49Smrg   glMatrixMode(GL_MODELVIEW);
9732001f49Smrg   glLoadIdentity();
9832001f49Smrg   glTranslatef(0, 0, -2);
9932001f49Smrg
10032001f49Smrg   Width = width;
10132001f49Smrg   Height = height;
10232001f49Smrg}
10332001f49Smrg
10432001f49Smrg
10532001f49Smrgstatic void
10632001f49SmrgCleanUp(void)
10732001f49Smrg{
10832001f49Smrg   glDeleteShader(FragShader1);
10932001f49Smrg   glDeleteShader(FragShader2);
11032001f49Smrg   glDeleteShader(VertShader1);
11132001f49Smrg   glDeleteShader(VertShader2);
11232001f49Smrg   glDeleteProgram(Program1);
11332001f49Smrg   glDeleteProgram(Program2);
11432001f49Smrg   glutDestroyWindow(Win);
11532001f49Smrg}
11632001f49Smrg
11732001f49Smrg
11832001f49Smrgstatic void
11932001f49SmrgKey(unsigned char key, int x, int y)
12032001f49Smrg{
12132001f49Smrg  (void) x;
12232001f49Smrg  (void) y;
12332001f49Smrg
12432001f49Smrg   switch(key) {
12532001f49Smrg   case 27:
12632001f49Smrg      CleanUp();
12732001f49Smrg      exit(0);
12832001f49Smrg      break;
12932001f49Smrg   }
13032001f49Smrg   glutPostRedisplay();
13132001f49Smrg}
13232001f49Smrg
13332001f49Smrg
13432001f49Smrgstatic void
13532001f49SmrgInit(void)
13632001f49Smrg{
13732001f49Smrg   /**
13832001f49Smrg    * Regular perspective interpolation
13932001f49Smrg    */
14032001f49Smrg   static const char *VertShaderText1 =
14132001f49Smrg      "void main() {\n"
14232001f49Smrg      "   vec4 pos = ftransform();\n"
14332001f49Smrg      "   gl_TexCoord[0] = gl_MultiTexCoord0; \n"
14432001f49Smrg      "   gl_Position = pos;\n"
14532001f49Smrg      "}\n";
14632001f49Smrg
14732001f49Smrg   static const char *FragShaderText1 =
14832001f49Smrg      "void main() {\n"
14932001f49Smrg      "   float gray = gl_TexCoord[0].y; \n"
15032001f49Smrg      "   gl_FragColor = vec4(gray); \n"
15132001f49Smrg      "}\n";
15232001f49Smrg
15332001f49Smrg   /**
15432001f49Smrg    * Perspective interpolation, converted to linear interpolation
15532001f49Smrg    * (put window position W in texcoord.w)
15632001f49Smrg    */
15732001f49Smrg   static const char *VertShaderText2 =
15832001f49Smrg      "void main() {\n"
15932001f49Smrg      "   vec4 pos = ftransform();\n"
16032001f49Smrg      "   gl_TexCoord[0] = gl_MultiTexCoord0 * pos.w; \n"
16132001f49Smrg      "   gl_TexCoord[0].w = pos.w; \n"
16232001f49Smrg      "   gl_Position = pos;\n"
16332001f49Smrg      "}\n";
16432001f49Smrg
16532001f49Smrg   static const char *FragShaderText2 =
16632001f49Smrg      "void main() {\n"
16732001f49Smrg      "   float gray = gl_TexCoord[0].y / gl_TexCoord[0].w; \n"
16832001f49Smrg      "   gl_FragColor = vec4(gray); \n"
16932001f49Smrg      "}\n";
17032001f49Smrg
17132001f49Smrg   if (!ShadersSupported())
17232001f49Smrg      exit(1);
17332001f49Smrg
17432001f49Smrg   VertShader1 = CompileShaderText(GL_VERTEX_SHADER, VertShaderText1);
17532001f49Smrg   VertShader2 = CompileShaderText(GL_VERTEX_SHADER, VertShaderText2);
17632001f49Smrg
17732001f49Smrg   FragShader1 = CompileShaderText(GL_FRAGMENT_SHADER, FragShaderText1);
17832001f49Smrg   FragShader2 = CompileShaderText(GL_FRAGMENT_SHADER, FragShaderText2);
17932001f49Smrg
18032001f49Smrg   Program1 = LinkShaders(VertShader1, FragShader1);
18132001f49Smrg   Program2 = LinkShaders(VertShader2, FragShader2);
18232001f49Smrg
18332001f49Smrg   glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
18432001f49Smrg   glEnable(GL_DEPTH_TEST);
18532001f49Smrg
18632001f49Smrg   printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
18732001f49Smrg
18832001f49Smrg   assert(glIsProgram(Program1));
18932001f49Smrg   assert(glIsProgram(Program2));
19032001f49Smrg   assert(glIsShader(VertShader1));
19132001f49Smrg   assert(glIsShader(VertShader2));
19232001f49Smrg   assert(glIsShader(FragShader1));
19332001f49Smrg   assert(glIsShader(FragShader2));
19432001f49Smrg
19532001f49Smrg   glColor3f(1, 0, 0);
19632001f49Smrg}
19732001f49Smrg
19832001f49Smrg
19932001f49Smrgint
20032001f49Smrgmain(int argc, char *argv[])
20132001f49Smrg{
20232001f49Smrg   glutInit(&argc, argv);
20332001f49Smrg   glutInitWindowSize(Width, Height);
20432001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
20532001f49Smrg   Win = glutCreateWindow(argv[0]);
20632001f49Smrg   glewInit();
20732001f49Smrg   glutReshapeFunc(Reshape);
20832001f49Smrg   glutKeyboardFunc(Key);
20932001f49Smrg   glutDisplayFunc(Redisplay);
21032001f49Smrg   Init();
21132001f49Smrg   glutMainLoop();
21232001f49Smrg   return 0;
21332001f49Smrg}
214