blob: 672a00491e6231eef613592d0404329d884deb4b [file] [log] [blame]
Brian87002ab2007-12-18 16:21:49 -07001/**
2 * Test two-sided lighting with shaders.
3 * Both GL_VERTEX_PROGRAM_TWO_SIDE and gl_FrontFacing can be tested
4 * (see keys below).
5 *
6 * Brian Paul
7 * 18 Dec 2007
8 */
9
10#include <assert.h>
11#include <string.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <math.h>
15#include <GL/gl.h>
16#include <GL/glut.h>
17#include <GL/glext.h>
18#include "extfuncs.h"
Brian2dca3372008-04-09 22:28:23 -060019#include "shaderutil.h"
Brian87002ab2007-12-18 16:21:49 -070020
21
Brian87002ab2007-12-18 16:21:49 -070022static GLint WinWidth = 300, WinHeight = 300;
23static char *FragProgFile = NULL;
24static char *VertProgFile = NULL;
25static GLuint fragShader;
26static GLuint vertShader;
27static GLuint program;
28static GLint win = 0;
29static GLboolean anim = 0*GL_TRUE;
30static GLboolean DetermineInFragProg = GL_TRUE;
Brian Paul1b39b922008-08-15 17:01:35 -060031static GLfloat Xrot = 30.0f;
Brian87002ab2007-12-18 16:21:49 -070032static GLint u_fragface;
33static GLenum FrontWinding = GL_CCW;
34static int prevTime = 0;
35
36
37static const GLfloat Red[4] = {1, 0, 0, 0};
38static const GLfloat Green[4] = {0, 1, 0, 0};
39
40
41static void
42Redisplay(void)
43{
Brian Paul1b39b922008-08-15 17:01:35 -060044 int i;
45 float radius = 2;
Brian87002ab2007-12-18 16:21:49 -070046
47 glFrontFace(FrontWinding);
48
49 if (DetermineInFragProg) {
50 glUniform1i_func(u_fragface, 1);
51 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
52 }
53 else {
54 glUniform1i_func(u_fragface, 0);
55 glEnable(GL_VERTEX_PROGRAM_TWO_SIDE);
56 }
57
Brian Paul1b39b922008-08-15 17:01:35 -060058 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Brian87002ab2007-12-18 16:21:49 -070059
60 glPushMatrix();
Brian Paul1b39b922008-08-15 17:01:35 -060061 glRotatef(Xrot, 1, 0, 0);
Brian87002ab2007-12-18 16:21:49 -070062
Brian Paul1b39b922008-08-15 17:01:35 -060063 /* Draw a tristrip ring */
64 glBegin(GL_TRIANGLE_STRIP);
Brian87002ab2007-12-18 16:21:49 -070065 glColor4fv(Red);
66 glSecondaryColor3fv_func(Green);
Brian Paul1b39b922008-08-15 17:01:35 -060067 for (i = 0; i < 20; i++) {
68 float a = i / 19.0 * M_PI * 2.0;
69 float x = radius * cos(a);
70 float y = radius * sin(a);
71 glVertex3f(x, -1, y);
72 glVertex3f(x, +1, y);
73 }
Brian87002ab2007-12-18 16:21:49 -070074 glEnd();
75
76 glPopMatrix();
77
78 glutSwapBuffers();
79}
80
81
82static void
83Idle(void)
84{
85 int curTime = glutGet(GLUT_ELAPSED_TIME);
86 int dt = curTime - prevTime;
87
88 if (prevTime == 0) {
89 prevTime = curTime;
90 return;
91 }
92 prevTime = curTime;
93
Brian Paul1b39b922008-08-15 17:01:35 -060094 Xrot += dt * 0.1;
Brian87002ab2007-12-18 16:21:49 -070095 glutPostRedisplay();
96}
97
98
99static void
100Reshape(int width, int height)
101{
102 float ar = (float) width / height;
103 glViewport(0, 0, width, height);
104 glMatrixMode(GL_PROJECTION);
105 glLoadIdentity();
Brian Paul1b39b922008-08-15 17:01:35 -0600106 glFrustum(-ar, ar, -1, 1, 3, 25);
Brian87002ab2007-12-18 16:21:49 -0700107 glMatrixMode(GL_MODELVIEW);
108 glLoadIdentity();
109 glTranslatef(0, 0, -10);
110}
111
112
113static void
114CleanUp(void)
115{
116 glDeleteShader_func(fragShader);
117 glDeleteShader_func(vertShader);
118 glDeleteProgram_func(program);
119 glutDestroyWindow(win);
120}
121
122
123static void
124Key(unsigned char key, int x, int y)
125{
126 (void) x;
127 (void) y;
128
129 switch(key) {
130 case ' ':
131 case 'a':
132 anim = !anim;
133 if (anim) {
134 prevTime = glutGet(GLUT_ELAPSED_TIME);
135 glutIdleFunc(Idle);
136 }
137 else
138 glutIdleFunc(NULL);
139 break;
140 case 'f':
141 printf("Using frag shader gl_FrontFacing\n");
142 DetermineInFragProg = GL_TRUE;
143 break;
144 case 'v':
145 printf("Using vert shader Two-sided lighting\n");
146 DetermineInFragProg = GL_FALSE;
147 break;
148 case 'r':
Brian Paul1b39b922008-08-15 17:01:35 -0600149 /* reset */
150 Xrot = 30;
Brian87002ab2007-12-18 16:21:49 -0700151 anim = 0;
152 glutIdleFunc(NULL);
153 break;
154 case 's':
Brian Paul1b39b922008-08-15 17:01:35 -0600155 Xrot += 5;
156 break;
157 case 'S':
158 Xrot -= 5;
Brian87002ab2007-12-18 16:21:49 -0700159 break;
160 case 'w':
161 if (FrontWinding == GL_CCW) {
162 FrontWinding = GL_CW;
163 printf("FrontFace = GL_CW\n");
164 }
165 else {
166 FrontWinding = GL_CCW;
167 printf("FrontFace = GL_CCW\n");
168 }
169 break;
170 case 27:
171 CleanUp();
172 exit(0);
173 break;
174 }
175 glutPostRedisplay();
176}
177
178
179static void
Brian87002ab2007-12-18 16:21:49 -0700180Init(void)
181{
182 static const char *fragShaderText =
183 "uniform bool fragface; \n"
184 "void main() { \n"
Brian Paul1b39b922008-08-15 17:01:35 -0600185#if 0
Brian87002ab2007-12-18 16:21:49 -0700186 " if (!fragface || gl_FrontFacing) { \n"
187 " gl_FragColor = gl_Color; \n"
188 " } \n"
189 " else { \n"
190 " gl_FragColor = 0.8 * gl_SecondaryColor; \n"
191 " } \n"
Brian Paul1b39b922008-08-15 17:01:35 -0600192#else
193 " bool f = gl_FrontFacing; \n"
194 " if (f) { \n"
195 " gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0); \n"
196 " } \n"
197 " else { \n"
198 " gl_FragColor = vec4(0.0, 1.0, 0.0, 0.0); \n"
199 " } \n"
200 " //float g = float(gl_FrontFacing) * 0.5 + 0.5; \n"
201 " //gl_FragColor = vec4(g); \n"
202#endif
Brian87002ab2007-12-18 16:21:49 -0700203 "} \n";
204 static const char *vertShaderText =
205 "uniform bool fragface; \n"
206 "void main() { \n"
207 " gl_FrontColor = gl_Color; \n"
208 " if (fragface) { \n"
209 " // front/back chosen in frag prog \n"
210 " gl_FrontSecondaryColor = gl_SecondaryColor; \n"
211 " } \n"
212 " else { \n"
213 " // front/back chosen in prim setup \n"
214 " gl_BackColor = gl_SecondaryColor; \n"
215 " } \n"
216 " gl_Position = ftransform(); \n"
217 "} \n";
Brian87002ab2007-12-18 16:21:49 -0700218
Brian2dca3372008-04-09 22:28:23 -0600219 if (!ShadersSupported())
Brian87002ab2007-12-18 16:21:49 -0700220 exit(1);
Brian87002ab2007-12-18 16:21:49 -0700221
222 GetExtensionFuncs();
223
Brian2dca3372008-04-09 22:28:23 -0600224 vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
225 fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
226 program = LinkShaders(vertShader, fragShader);
Brian87002ab2007-12-18 16:21:49 -0700227
Brian87002ab2007-12-18 16:21:49 -0700228 glUseProgram_func(program);
229
230 u_fragface = glGetUniformLocation_func(program, "fragface");
231 printf("Uniforms: %d\n", u_fragface);
232
233 /*assert(glGetError() == 0);*/
234
235 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
236
237 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
238
239 assert(glIsProgram_func(program));
240 assert(glIsShader_func(fragShader));
241 assert(glIsShader_func(vertShader));
Brian Paul1b39b922008-08-15 17:01:35 -0600242
243 glEnable(GL_DEPTH_TEST);
Brian87002ab2007-12-18 16:21:49 -0700244}
245
246
247static void
248ParseOptions(int argc, char *argv[])
249{
250 int i;
251 for (i = 1; i < argc; i++) {
252 if (strcmp(argv[i], "-fs") == 0) {
253 FragProgFile = argv[i+1];
254 }
255 else if (strcmp(argv[i], "-vs") == 0) {
256 VertProgFile = argv[i+1];
257 }
258 }
259}
260
261
262static void
263Usage(void)
264{
265 printf("Keys:\n");
266 printf(" f - do front/back determination in fragment shader\n");
267 printf(" v - do front/back determination in vertex shader\n");
268 printf(" r - reset, show front\n");
269 printf(" a - toggle animation\n");
270 printf(" s - step rotation\n");
271 printf(" w - toggle CW, CCW front-face winding\n");
Brian Paul1b39b922008-08-15 17:01:35 -0600272 printf("NOTE: red = front face, green = back face.\n");
Brian87002ab2007-12-18 16:21:49 -0700273}
274
275
276int
277main(int argc, char *argv[])
278{
279 glutInit(&argc, argv);
280 glutInitWindowPosition( 0, 0);
281 glutInitWindowSize(WinWidth, WinHeight);
Brian Paul1b39b922008-08-15 17:01:35 -0600282 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
Brian87002ab2007-12-18 16:21:49 -0700283 win = glutCreateWindow(argv[0]);
284 glutReshapeFunc(Reshape);
285 glutKeyboardFunc(Key);
286 glutDisplayFunc(Redisplay);
287 if (anim)
288 glutIdleFunc(Idle);
289 ParseOptions(argc, argv);
290 Init();
291 Usage();
292 glutMainLoop();
293 return 0;
294}