blob: 9ebc4ec36071430fb1e3e2eb79e71927baaa3671 [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>
Keith Whitwellb799af92009-06-29 14:13:58 +010015#include <GL/glew.h>
Brian87002ab2007-12-18 16:21:49 -070016#include <GL/gl.h>
17#include <GL/glut.h>
18#include <GL/glext.h>
19#include "extfuncs.h"
Brian2dca3372008-04-09 22:28:23 -060020#include "shaderutil.h"
Brian87002ab2007-12-18 16:21:49 -070021
22
Brian87002ab2007-12-18 16:21:49 -070023static GLint WinWidth = 300, WinHeight = 300;
24static char *FragProgFile = NULL;
25static char *VertProgFile = NULL;
26static GLuint fragShader;
27static GLuint vertShader;
28static GLuint program;
29static GLint win = 0;
Brian Paulc9122072008-12-18 16:08:42 -070030static GLboolean anim;
31static GLboolean DetermineFacingInFragProg;
32static GLfloat Xrot;
Brian87002ab2007-12-18 16:21:49 -070033static GLint u_fragface;
Brian Paulc9122072008-12-18 16:08:42 -070034static GLenum FrontWinding;
Brian87002ab2007-12-18 16:21:49 -070035static int prevTime = 0;
36
37
Brian Paulc9122072008-12-18 16:08:42 -070038static const GLfloat Red[4] = {1, 0, 0, 1};
Brian87002ab2007-12-18 16:21:49 -070039static const GLfloat Green[4] = {0, 1, 0, 0};
40
41
42static void
Brian Paulc9122072008-12-18 16:08:42 -070043SetDefaults(void)
44{
45 DetermineFacingInFragProg = GL_TRUE;
46 FrontWinding = GL_CCW;
47 Xrot = 30;
48 anim = 0;
49 glutIdleFunc(NULL);
50}
51
52
53static void
Brian87002ab2007-12-18 16:21:49 -070054Redisplay(void)
55{
Brian Paulc9122072008-12-18 16:08:42 -070056 const int sections = 20;
Brian Paul1b39b922008-08-15 17:01:35 -060057 int i;
58 float radius = 2;
Brian87002ab2007-12-18 16:21:49 -070059
60 glFrontFace(FrontWinding);
61
Brian Paulc9122072008-12-18 16:08:42 -070062 if (DetermineFacingInFragProg) {
Brian87002ab2007-12-18 16:21:49 -070063 glUniform1i_func(u_fragface, 1);
64 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
65 }
66 else {
67 glUniform1i_func(u_fragface, 0);
68 glEnable(GL_VERTEX_PROGRAM_TWO_SIDE);
69 }
70
Brian Paul1b39b922008-08-15 17:01:35 -060071 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Brian87002ab2007-12-18 16:21:49 -070072
73 glPushMatrix();
Brian Paul1b39b922008-08-15 17:01:35 -060074 glRotatef(Xrot, 1, 0, 0);
Brian87002ab2007-12-18 16:21:49 -070075
Brian Paul1b39b922008-08-15 17:01:35 -060076 /* Draw a tristrip ring */
77 glBegin(GL_TRIANGLE_STRIP);
Brian87002ab2007-12-18 16:21:49 -070078 glColor4fv(Red);
79 glSecondaryColor3fv_func(Green);
Brian Paulc9122072008-12-18 16:08:42 -070080 for (i = 0; i <= sections; i++) {
81 float a = (float) i / (sections) * M_PI * 2.0;
Brian Paul1b39b922008-08-15 17:01:35 -060082 float x = radius * cos(a);
83 float y = radius * sin(a);
84 glVertex3f(x, -1, y);
85 glVertex3f(x, +1, y);
86 }
Brian87002ab2007-12-18 16:21:49 -070087 glEnd();
88
89 glPopMatrix();
90
91 glutSwapBuffers();
92}
93
94
95static void
96Idle(void)
97{
98 int curTime = glutGet(GLUT_ELAPSED_TIME);
99 int dt = curTime - prevTime;
100
101 if (prevTime == 0) {
102 prevTime = curTime;
103 return;
104 }
105 prevTime = curTime;
106
Brian Paul1b39b922008-08-15 17:01:35 -0600107 Xrot += dt * 0.1;
Brian87002ab2007-12-18 16:21:49 -0700108 glutPostRedisplay();
109}
110
111
112static void
113Reshape(int width, int height)
114{
115 float ar = (float) width / height;
116 glViewport(0, 0, width, height);
117 glMatrixMode(GL_PROJECTION);
118 glLoadIdentity();
Brian Paul1b39b922008-08-15 17:01:35 -0600119 glFrustum(-ar, ar, -1, 1, 3, 25);
Brian87002ab2007-12-18 16:21:49 -0700120 glMatrixMode(GL_MODELVIEW);
121 glLoadIdentity();
122 glTranslatef(0, 0, -10);
123}
124
125
126static void
127CleanUp(void)
128{
129 glDeleteShader_func(fragShader);
130 glDeleteShader_func(vertShader);
131 glDeleteProgram_func(program);
132 glutDestroyWindow(win);
133}
134
135
136static void
137Key(unsigned char key, int x, int y)
138{
139 (void) x;
140 (void) y;
141
142 switch(key) {
143 case ' ':
144 case 'a':
145 anim = !anim;
146 if (anim) {
147 prevTime = glutGet(GLUT_ELAPSED_TIME);
148 glutIdleFunc(Idle);
149 }
150 else
151 glutIdleFunc(NULL);
152 break;
153 case 'f':
154 printf("Using frag shader gl_FrontFacing\n");
Brian Paulc9122072008-12-18 16:08:42 -0700155 DetermineFacingInFragProg = GL_TRUE;
Brian87002ab2007-12-18 16:21:49 -0700156 break;
157 case 'v':
158 printf("Using vert shader Two-sided lighting\n");
Brian Paulc9122072008-12-18 16:08:42 -0700159 DetermineFacingInFragProg = GL_FALSE;
Brian87002ab2007-12-18 16:21:49 -0700160 break;
161 case 'r':
Brian Paul1b39b922008-08-15 17:01:35 -0600162 /* reset */
Brian Paulc9122072008-12-18 16:08:42 -0700163 SetDefaults();
Brian87002ab2007-12-18 16:21:49 -0700164 break;
165 case 's':
Brian Paul1b39b922008-08-15 17:01:35 -0600166 Xrot += 5;
167 break;
168 case 'S':
169 Xrot -= 5;
Brian87002ab2007-12-18 16:21:49 -0700170 break;
171 case 'w':
172 if (FrontWinding == GL_CCW) {
173 FrontWinding = GL_CW;
174 printf("FrontFace = GL_CW\n");
175 }
176 else {
177 FrontWinding = GL_CCW;
178 printf("FrontFace = GL_CCW\n");
179 }
180 break;
181 case 27:
182 CleanUp();
183 exit(0);
184 break;
185 }
186 glutPostRedisplay();
187}
188
189
190static void
Brian87002ab2007-12-18 16:21:49 -0700191Init(void)
192{
193 static const char *fragShaderText =
194 "uniform bool fragface; \n"
195 "void main() { \n"
Brian Paulc9122072008-12-18 16:08:42 -0700196#if 1
Brian87002ab2007-12-18 16:21:49 -0700197 " if (!fragface || gl_FrontFacing) { \n"
198 " gl_FragColor = gl_Color; \n"
199 " } \n"
200 " else { \n"
Brian Paulc9122072008-12-18 16:08:42 -0700201 " // note: dim green to help debug \n"
Brian87002ab2007-12-18 16:21:49 -0700202 " gl_FragColor = 0.8 * gl_SecondaryColor; \n"
203 " } \n"
Brian Paul1b39b922008-08-15 17:01:35 -0600204#else
Brian Paulc9122072008-12-18 16:08:42 -0700205 /* DEBUG CODE */
Brian Paul1b39b922008-08-15 17:01:35 -0600206 " bool f = gl_FrontFacing; \n"
207 " if (f) { \n"
208 " gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0); \n"
209 " } \n"
210 " else { \n"
211 " gl_FragColor = vec4(0.0, 1.0, 0.0, 0.0); \n"
212 " } \n"
Brian Paul1b39b922008-08-15 17:01:35 -0600213#endif
Brian87002ab2007-12-18 16:21:49 -0700214 "} \n";
215 static const char *vertShaderText =
216 "uniform bool fragface; \n"
217 "void main() { \n"
218 " gl_FrontColor = gl_Color; \n"
219 " if (fragface) { \n"
220 " // front/back chosen in frag prog \n"
221 " gl_FrontSecondaryColor = gl_SecondaryColor; \n"
222 " } \n"
223 " else { \n"
224 " // front/back chosen in prim setup \n"
225 " gl_BackColor = gl_SecondaryColor; \n"
226 " } \n"
227 " gl_Position = ftransform(); \n"
228 "} \n";
Brian87002ab2007-12-18 16:21:49 -0700229
Brian2dca3372008-04-09 22:28:23 -0600230 if (!ShadersSupported())
Brian87002ab2007-12-18 16:21:49 -0700231 exit(1);
Brian87002ab2007-12-18 16:21:49 -0700232
233 GetExtensionFuncs();
234
Brian2dca3372008-04-09 22:28:23 -0600235 vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
236 fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
237 program = LinkShaders(vertShader, fragShader);
Brian87002ab2007-12-18 16:21:49 -0700238
Brian87002ab2007-12-18 16:21:49 -0700239 glUseProgram_func(program);
240
241 u_fragface = glGetUniformLocation_func(program, "fragface");
242 printf("Uniforms: %d\n", u_fragface);
243
244 /*assert(glGetError() == 0);*/
245
246 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
247
248 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
249
250 assert(glIsProgram_func(program));
251 assert(glIsShader_func(fragShader));
252 assert(glIsShader_func(vertShader));
Brian Paul1b39b922008-08-15 17:01:35 -0600253
254 glEnable(GL_DEPTH_TEST);
Brian Paulc9122072008-12-18 16:08:42 -0700255
256 SetDefaults();
Brian87002ab2007-12-18 16:21:49 -0700257}
258
259
260static void
261ParseOptions(int argc, char *argv[])
262{
263 int i;
264 for (i = 1; i < argc; i++) {
265 if (strcmp(argv[i], "-fs") == 0) {
266 FragProgFile = argv[i+1];
267 }
268 else if (strcmp(argv[i], "-vs") == 0) {
269 VertProgFile = argv[i+1];
270 }
271 }
272}
273
274
275static void
276Usage(void)
277{
278 printf("Keys:\n");
279 printf(" f - do front/back determination in fragment shader\n");
280 printf(" v - do front/back determination in vertex shader\n");
281 printf(" r - reset, show front\n");
282 printf(" a - toggle animation\n");
283 printf(" s - step rotation\n");
284 printf(" w - toggle CW, CCW front-face winding\n");
Brian Paul1b39b922008-08-15 17:01:35 -0600285 printf("NOTE: red = front face, green = back face.\n");
Brian87002ab2007-12-18 16:21:49 -0700286}
287
288
289int
290main(int argc, char *argv[])
291{
292 glutInit(&argc, argv);
293 glutInitWindowPosition( 0, 0);
294 glutInitWindowSize(WinWidth, WinHeight);
Brian Paul1b39b922008-08-15 17:01:35 -0600295 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
Brian87002ab2007-12-18 16:21:49 -0700296 win = glutCreateWindow(argv[0]);
Keith Whitwellb799af92009-06-29 14:13:58 +0100297 glewInit();
Brian87002ab2007-12-18 16:21:49 -0700298 glutReshapeFunc(Reshape);
299 glutKeyboardFunc(Key);
300 glutDisplayFunc(Redisplay);
301 if (anim)
302 glutIdleFunc(Idle);
303 ParseOptions(argc, argv);
304 Init();
305 Usage();
306 glutMainLoop();
307 return 0;
308}