2 * Use GL_NV_fragment_program to implement per-pixel lighting.
13 #include <glad/glad.h>
14 #include "glut_wrap.h"
17 static GLfloat Diffuse
[4] = { 0.5, 0.5, 1.0, 1.0 };
18 static GLfloat Specular
[4] = { 0.8, 0.8, 0.8, 1.0 };
19 static GLfloat LightPos
[4] = { 0.0, 10.0, 20.0, 1.0 };
20 static GLfloat Delta
= 1.0;
22 static GLuint FragProg
;
23 static GLuint VertProg
;
24 static GLboolean Anim
= GL_TRUE
;
25 static GLboolean Wire
= GL_FALSE
;
26 static GLboolean PixelLight
= GL_TRUE
;
28 static GLfloat Xrot
= 0, Yrot
= 0;
31 #define NAMED_PARAMETER4FV(prog, name, v) \
32 glProgramNamedParameter4fvNV(prog, strlen(name), (const GLubyte *) name, v)
35 static void Display( void )
37 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
40 #if defined(GL_NV_fragment_program)
41 NAMED_PARAMETER4FV(FragProg
, "LightPos", LightPos
);
42 glEnable(GL_FRAGMENT_PROGRAM_NV
);
43 glEnable(GL_VERTEX_PROGRAM_NV
);
45 glDisable(GL_LIGHTING
);
48 glLightfv(GL_LIGHT0
, GL_POSITION
, LightPos
);
49 #if defined(GL_NV_fragment_program)
50 glDisable(GL_FRAGMENT_PROGRAM_NV
);
51 glDisable(GL_VERTEX_PROGRAM_NV
);
53 glEnable(GL_LIGHTING
);
57 glRotatef(Xrot
, 1, 0, 0);
58 glRotatef(Yrot
, 0, 1, 0);
61 glutSolidSphere(2.0, 10, 5);
64 GLUquadricObj
*q
= gluNewQuadric();
65 gluQuadricNormals(q
, GL_SMOOTH
);
66 gluQuadricTexture(q
, GL_TRUE
);
67 glRotatef(90, 1, 0, 0);
68 glTranslatef(0, 0, -1);
69 gluCylinder(q
, 1.0, 1.0, 2.0, 24, 1);
80 static void Idle(void)
83 if (LightPos
[0] > 25.0)
85 else if (LightPos
[0] <- 25.0)
91 static void Reshape( int width
, int height
)
93 glViewport( 0, 0, width
, height
);
94 glMatrixMode( GL_PROJECTION
);
96 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
97 /*glOrtho( -2.0, 2.0, -2.0, 2.0, 5.0, 25.0 );*/
98 glMatrixMode( GL_MODELVIEW
);
100 glTranslatef( 0.0, 0.0, -15.0 );
104 static void Key( unsigned char key
, int x
, int y
)
125 glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
);
127 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
130 PixelLight
= !PixelLight
;
132 printf("Per-pixel lighting\n");
135 printf("Conventional lighting\n");
139 glutDestroyWindow(Win
);
145 static void SpecialKey( int key
, int x
, int y
)
147 const GLfloat step
= 3.0;
168 static void Init( void )
170 static const char *fragProgramText
=
172 "DECLARE Diffuse; \n"
173 "DECLARE Specular; \n"
174 "DECLARE LightPos; \n"
176 "# Compute normalized LightPos, put it in R0\n"
177 "DP3 R0.x, LightPos, LightPos;\n"
179 "MUL R0, LightPos, R0.y;\n"
181 "# Compute normalized normal, put it in R1\n"
182 "DP3 R1, f[TEX0], f[TEX0]; \n"
184 "MUL R1, f[TEX0], R1.y;\n"
186 "# Compute dot product of light direction and normal vector\n"
187 "DP3_SAT R2, R0, R1;"
189 "MUL R3, Diffuse, R2; # diffuse attenuation\n"
191 "POW R4, R2.x, {20.0}.x; # specular exponent\n"
193 "MUL R5, Specular, R4; # specular attenuation\n"
195 "ADD o[COLR], R3, R5; # add diffuse and specular colors\n"
199 static const char *vertProgramText
=
201 "# typical modelview/projection transform\n"
202 "DP4 o[HPOS].x, c[0], v[OPOS] ;\n"
203 "DP4 o[HPOS].y, c[1], v[OPOS] ;\n"
204 "DP4 o[HPOS].z, c[2], v[OPOS] ;\n"
205 "DP4 o[HPOS].w, c[3], v[OPOS] ;\n"
206 "# transform normal by inv transpose of modelview, put in tex0\n"
207 "DP3 o[TEX0].x, c[4], v[NRML] ;\n"
208 "DP3 o[TEX0].y, c[5], v[NRML] ;\n"
209 "DP3 o[TEX0].z, c[6], v[NRML] ;\n"
210 "DP3 o[TEX0].w, c[7], v[NRML] ;\n"
214 if (!glutExtensionSupported("GL_NV_vertex_program")) {
215 printf("Sorry, this demo requires GL_NV_vertex_program\n");
218 if (!glutExtensionSupported("GL_NV_fragment_program")) {
219 printf("Sorry, this demo requires GL_NV_fragment_program\n");
223 #if defined(GL_NV_fragment_program)
224 glGenProgramsNV(1, &FragProg
);
225 assert(FragProg
> 0);
226 glGenProgramsNV(1, &VertProg
);
227 assert(VertProg
> 0);
232 glLoadProgramNV(GL_FRAGMENT_PROGRAM_NV
, FragProg
,
233 strlen(fragProgramText
),
234 (const GLubyte
*) fragProgramText
);
235 assert(glIsProgramNV(FragProg
));
236 glBindProgramNV(GL_FRAGMENT_PROGRAM_NV
, FragProg
);
238 NAMED_PARAMETER4FV(FragProg
, "Diffuse", Diffuse
);
239 NAMED_PARAMETER4FV(FragProg
, "Specular", Specular
);
244 glLoadProgramNV(GL_VERTEX_PROGRAM_NV
, VertProg
,
245 strlen(vertProgramText
),
246 (const GLubyte
*) vertProgramText
);
247 assert(glIsProgramNV(VertProg
));
248 glBindProgramNV(GL_VERTEX_PROGRAM_NV
, VertProg
);
249 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV
, 0, GL_MODELVIEW_PROJECTION_NV
, GL_IDENTITY_NV
);
250 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV
, 4, GL_MODELVIEW
, GL_INVERSE_TRANSPOSE_NV
);
256 glClearColor(0.3, 0.3, 0.3, 0.0);
257 glEnable(GL_DEPTH_TEST
);
259 glEnable(GL_LIGHTING
);
260 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, Diffuse
);
261 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, Specular
);
262 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 20.0);
264 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
265 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
269 int main( int argc
, char *argv
[] )
271 glutInitWindowSize( 200, 200 );
272 glutInit( &argc
, argv
);
273 glutInitDisplayMode( GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
274 Win
= glutCreateWindow(argv
[0]);
276 glutReshapeFunc( Reshape
);
277 glutKeyboardFunc( Key
);
278 glutSpecialFunc( SpecialKey
);
279 glutDisplayFunc( Display
);