132001f49Smrg/* 232001f49Smrg * Use GL_NV_fragment_program to implement per-pixel lighting. 332001f49Smrg * 432001f49Smrg * Brian Paul 532001f49Smrg * 7 April 2003 632001f49Smrg */ 732001f49Smrg 832001f49Smrg#include <assert.h> 932001f49Smrg#include <string.h> 1032001f49Smrg#include <stdio.h> 1132001f49Smrg#include <stdlib.h> 1232001f49Smrg#include <math.h> 1332001f49Smrg#include <GL/glew.h> 1432001f49Smrg#include "glut_wrap.h" 1532001f49Smrg 1632001f49Smrg 1732001f49Smrgstatic GLfloat Diffuse[4] = { 0.5, 0.5, 1.0, 1.0 }; 1832001f49Smrgstatic GLfloat Specular[4] = { 0.8, 0.8, 0.8, 1.0 }; 1932001f49Smrgstatic GLfloat LightPos[4] = { 0.0, 10.0, 20.0, 1.0 }; 2032001f49Smrgstatic GLfloat Delta = 1.0; 2132001f49Smrg 2232001f49Smrgstatic GLuint FragProg; 2332001f49Smrgstatic GLuint VertProg; 2432001f49Smrgstatic GLboolean Anim = GL_TRUE; 2532001f49Smrgstatic GLboolean Wire = GL_FALSE; 2632001f49Smrgstatic GLboolean PixelLight = GL_TRUE; 2732001f49Smrgstatic GLint Win; 2832001f49Smrgstatic GLfloat Xrot = 0, Yrot = 0; 2932001f49Smrg 3032001f49Smrg 3132001f49Smrg#define NAMED_PARAMETER4FV(prog, name, v) \ 3232001f49Smrg glProgramNamedParameter4fvNV(prog, strlen(name), (const GLubyte *) name, v) 3332001f49Smrg 3432001f49Smrg 3532001f49Smrgstatic void Display( void ) 3632001f49Smrg{ 3732001f49Smrg glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 3832001f49Smrg 3932001f49Smrg if (PixelLight) { 4032001f49Smrg#if defined(GL_NV_fragment_program) 4132001f49Smrg NAMED_PARAMETER4FV(FragProg, "LightPos", LightPos); 4232001f49Smrg glEnable(GL_FRAGMENT_PROGRAM_NV); 4332001f49Smrg glEnable(GL_VERTEX_PROGRAM_NV); 4432001f49Smrg#endif 4532001f49Smrg glDisable(GL_LIGHTING); 4632001f49Smrg } 4732001f49Smrg else { 4832001f49Smrg glLightfv(GL_LIGHT0, GL_POSITION, LightPos); 4932001f49Smrg#if defined(GL_NV_fragment_program) 5032001f49Smrg glDisable(GL_FRAGMENT_PROGRAM_NV); 5132001f49Smrg glDisable(GL_VERTEX_PROGRAM_NV); 5232001f49Smrg#endif 5332001f49Smrg glEnable(GL_LIGHTING); 5432001f49Smrg } 5532001f49Smrg 5632001f49Smrg glPushMatrix(); 5732001f49Smrg glRotatef(Xrot, 1, 0, 0); 5832001f49Smrg glRotatef(Yrot, 0, 1, 0); 5932001f49Smrg 6032001f49Smrg#if 1 6132001f49Smrg glutSolidSphere(2.0, 10, 5); 6232001f49Smrg#else 6332001f49Smrg { 6432001f49Smrg GLUquadricObj *q = gluNewQuadric(); 6532001f49Smrg gluQuadricNormals(q, GL_SMOOTH); 6632001f49Smrg gluQuadricTexture(q, GL_TRUE); 6732001f49Smrg glRotatef(90, 1, 0, 0); 6832001f49Smrg glTranslatef(0, 0, -1); 6932001f49Smrg gluCylinder(q, 1.0, 1.0, 2.0, 24, 1); 7032001f49Smrg gluDeleteQuadric(q); 7132001f49Smrg } 7232001f49Smrg#endif 7332001f49Smrg 7432001f49Smrg glPopMatrix(); 7532001f49Smrg 7632001f49Smrg glutSwapBuffers(); 7732001f49Smrg} 7832001f49Smrg 7932001f49Smrg 8032001f49Smrgstatic void Idle(void) 8132001f49Smrg{ 8232001f49Smrg LightPos[0] += Delta; 8332001f49Smrg if (LightPos[0] > 25.0) 8432001f49Smrg Delta = -1.0; 8532001f49Smrg else if (LightPos[0] <- 25.0) 8632001f49Smrg Delta = 1.0; 8732001f49Smrg glutPostRedisplay(); 8832001f49Smrg} 8932001f49Smrg 9032001f49Smrg 9132001f49Smrgstatic void Reshape( int width, int height ) 9232001f49Smrg{ 9332001f49Smrg glViewport( 0, 0, width, height ); 9432001f49Smrg glMatrixMode( GL_PROJECTION ); 9532001f49Smrg glLoadIdentity(); 9632001f49Smrg glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 ); 9732001f49Smrg /*glOrtho( -2.0, 2.0, -2.0, 2.0, 5.0, 25.0 );*/ 9832001f49Smrg glMatrixMode( GL_MODELVIEW ); 9932001f49Smrg glLoadIdentity(); 10032001f49Smrg glTranslatef( 0.0, 0.0, -15.0 ); 10132001f49Smrg} 10232001f49Smrg 10332001f49Smrg 10432001f49Smrgstatic void Key( unsigned char key, int x, int y ) 10532001f49Smrg{ 10632001f49Smrg (void) x; 10732001f49Smrg (void) y; 10832001f49Smrg switch (key) { 10932001f49Smrg case ' ': 11032001f49Smrg Anim = !Anim; 11132001f49Smrg if (Anim) 11232001f49Smrg glutIdleFunc(Idle); 11332001f49Smrg else 11432001f49Smrg glutIdleFunc(NULL); 11532001f49Smrg break; 11632001f49Smrg case 'x': 11732001f49Smrg LightPos[0] -= 1.0; 11832001f49Smrg break; 11932001f49Smrg case 'X': 12032001f49Smrg LightPos[0] += 1.0; 12132001f49Smrg break; 12232001f49Smrg case 'w': 12332001f49Smrg Wire = !Wire; 12432001f49Smrg if (Wire) 12532001f49Smrg glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 12632001f49Smrg else 12732001f49Smrg glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 12832001f49Smrg break; 12932001f49Smrg case 'p': 13032001f49Smrg PixelLight = !PixelLight; 13132001f49Smrg if (PixelLight) { 13232001f49Smrg printf("Per-pixel lighting\n"); 13332001f49Smrg } 13432001f49Smrg else { 13532001f49Smrg printf("Conventional lighting\n"); 13632001f49Smrg } 13732001f49Smrg break; 13832001f49Smrg case 27: 13932001f49Smrg glutDestroyWindow(Win); 14032001f49Smrg exit(0); 14132001f49Smrg } 14232001f49Smrg glutPostRedisplay(); 14332001f49Smrg} 14432001f49Smrg 14532001f49Smrgstatic void SpecialKey( int key, int x, int y ) 14632001f49Smrg{ 14732001f49Smrg const GLfloat step = 3.0; 14832001f49Smrg (void) x; 14932001f49Smrg (void) y; 15032001f49Smrg switch (key) { 15132001f49Smrg case GLUT_KEY_UP: 15232001f49Smrg Xrot -= step; 15332001f49Smrg break; 15432001f49Smrg case GLUT_KEY_DOWN: 15532001f49Smrg Xrot += step; 15632001f49Smrg break; 15732001f49Smrg case GLUT_KEY_LEFT: 15832001f49Smrg Yrot -= step; 15932001f49Smrg break; 16032001f49Smrg case GLUT_KEY_RIGHT: 16132001f49Smrg Yrot += step; 16232001f49Smrg break; 16332001f49Smrg } 16432001f49Smrg glutPostRedisplay(); 16532001f49Smrg} 16632001f49Smrg 16732001f49Smrg 16832001f49Smrgstatic void Init( void ) 16932001f49Smrg{ 17032001f49Smrg static const char *fragProgramText = 17132001f49Smrg "!!FP1.0\n" 17232001f49Smrg "DECLARE Diffuse; \n" 17332001f49Smrg "DECLARE Specular; \n" 17432001f49Smrg "DECLARE LightPos; \n" 17532001f49Smrg 17632001f49Smrg "# Compute normalized LightPos, put it in R0\n" 17732001f49Smrg "DP3 R0.x, LightPos, LightPos;\n" 17832001f49Smrg "RSQ R0.y, R0.x;\n" 17932001f49Smrg "MUL R0, LightPos, R0.y;\n" 18032001f49Smrg 18132001f49Smrg "# Compute normalized normal, put it in R1\n" 18232001f49Smrg "DP3 R1, f[TEX0], f[TEX0]; \n" 18332001f49Smrg "RSQ R1.y, R1.x;\n" 18432001f49Smrg "MUL R1, f[TEX0], R1.y;\n" 18532001f49Smrg 18632001f49Smrg "# Compute dot product of light direction and normal vector\n" 18732001f49Smrg "DP3_SAT R2, R0, R1;" 18832001f49Smrg 18932001f49Smrg "MUL R3, Diffuse, R2; # diffuse attenuation\n" 19032001f49Smrg 19132001f49Smrg "POW R4, R2.x, {20.0}.x; # specular exponent\n" 19232001f49Smrg 19332001f49Smrg "MUL R5, Specular, R4; # specular attenuation\n" 19432001f49Smrg 19532001f49Smrg "ADD o[COLR], R3, R5; # add diffuse and specular colors\n" 19632001f49Smrg "END \n" 19732001f49Smrg ; 19832001f49Smrg 19932001f49Smrg static const char *vertProgramText = 20032001f49Smrg "!!VP1.0\n" 20132001f49Smrg "# typical modelview/projection transform\n" 20232001f49Smrg "DP4 o[HPOS].x, c[0], v[OPOS] ;\n" 20332001f49Smrg "DP4 o[HPOS].y, c[1], v[OPOS] ;\n" 20432001f49Smrg "DP4 o[HPOS].z, c[2], v[OPOS] ;\n" 20532001f49Smrg "DP4 o[HPOS].w, c[3], v[OPOS] ;\n" 20632001f49Smrg "# transform normal by inv transpose of modelview, put in tex0\n" 20732001f49Smrg "DP3 o[TEX0].x, c[4], v[NRML] ;\n" 20832001f49Smrg "DP3 o[TEX0].y, c[5], v[NRML] ;\n" 20932001f49Smrg "DP3 o[TEX0].z, c[6], v[NRML] ;\n" 21032001f49Smrg "DP3 o[TEX0].w, c[7], v[NRML] ;\n" 21132001f49Smrg "END\n"; 21232001f49Smrg ; 21332001f49Smrg 21432001f49Smrg if (!glutExtensionSupported("GL_NV_vertex_program")) { 21532001f49Smrg printf("Sorry, this demo requires GL_NV_vertex_program\n"); 21632001f49Smrg exit(1); 21732001f49Smrg } 21832001f49Smrg if (!glutExtensionSupported("GL_NV_fragment_program")) { 21932001f49Smrg printf("Sorry, this demo requires GL_NV_fragment_program\n"); 22032001f49Smrg exit(1); 22132001f49Smrg } 22232001f49Smrg 22332001f49Smrg#if defined(GL_NV_fragment_program) 22432001f49Smrg glGenProgramsNV(1, &FragProg); 22532001f49Smrg assert(FragProg > 0); 22632001f49Smrg glGenProgramsNV(1, &VertProg); 22732001f49Smrg assert(VertProg > 0); 22832001f49Smrg 22932001f49Smrg /* 23032001f49Smrg * Fragment program 23132001f49Smrg */ 23232001f49Smrg glLoadProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg, 23332001f49Smrg strlen(fragProgramText), 23432001f49Smrg (const GLubyte *) fragProgramText); 23532001f49Smrg assert(glIsProgramNV(FragProg)); 23632001f49Smrg glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg); 23732001f49Smrg 23832001f49Smrg NAMED_PARAMETER4FV(FragProg, "Diffuse", Diffuse); 23932001f49Smrg NAMED_PARAMETER4FV(FragProg, "Specular", Specular); 24032001f49Smrg 24132001f49Smrg /* 24232001f49Smrg * Vertex program 24332001f49Smrg */ 24432001f49Smrg glLoadProgramNV(GL_VERTEX_PROGRAM_NV, VertProg, 24532001f49Smrg strlen(vertProgramText), 24632001f49Smrg (const GLubyte *) vertProgramText); 24732001f49Smrg assert(glIsProgramNV(VertProg)); 24832001f49Smrg glBindProgramNV(GL_VERTEX_PROGRAM_NV, VertProg); 24932001f49Smrg glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV); 25032001f49Smrg glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_MODELVIEW, GL_INVERSE_TRANSPOSE_NV); 25132001f49Smrg#endif 25232001f49Smrg 25332001f49Smrg /* 25432001f49Smrg * Misc init 25532001f49Smrg */ 25632001f49Smrg glClearColor(0.3, 0.3, 0.3, 0.0); 25732001f49Smrg glEnable(GL_DEPTH_TEST); 25832001f49Smrg glEnable(GL_LIGHT0); 25932001f49Smrg glEnable(GL_LIGHTING); 26032001f49Smrg glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Diffuse); 26132001f49Smrg glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Specular); 26232001f49Smrg glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0); 26332001f49Smrg 26432001f49Smrg printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 26532001f49Smrg printf("Press p to toggle between per-pixel and per-vertex lighting\n"); 26632001f49Smrg} 26732001f49Smrg 26832001f49Smrg 26932001f49Smrgint main( int argc, char *argv[] ) 27032001f49Smrg{ 27132001f49Smrg glutInitWindowSize( 200, 200 ); 27232001f49Smrg glutInit( &argc, argv ); 27332001f49Smrg glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); 27432001f49Smrg Win = glutCreateWindow(argv[0]); 27532001f49Smrg glewInit(); 27632001f49Smrg glutReshapeFunc( Reshape ); 27732001f49Smrg glutKeyboardFunc( Key ); 27832001f49Smrg glutSpecialFunc( SpecialKey ); 27932001f49Smrg glutDisplayFunc( Display ); 28032001f49Smrg if (Anim) 28132001f49Smrg glutIdleFunc(Idle); 28232001f49Smrg Init(); 28332001f49Smrg glutMainLoop(); 28432001f49Smrg return 0; 28532001f49Smrg} 286