blob: 06488bd1759d74187dd2143beef5cdd00acc611e [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;
Brian Paulc9122072008-12-18 16:08:42 -070029static GLboolean anim;
30static GLboolean DetermineFacingInFragProg;
31static GLfloat Xrot;
Brian87002ab2007-12-18 16:21:49 -070032static GLint u_fragface;
Brian Paulc9122072008-12-18 16:08:42 -070033static GLenum FrontWinding;
Brian87002ab2007-12-18 16:21:49 -070034static int prevTime = 0;
35
36
Brian Paulc9122072008-12-18 16:08:42 -070037static const GLfloat Red[4] = {1, 0, 0, 1};
Brian87002ab2007-12-18 16:21:49 -070038static const GLfloat Green[4] = {0, 1, 0, 0};
39
40
41static void
Brian Paulc9122072008-12-18 16:08:42 -070042SetDefaults(void)
43{
44 DetermineFacingInFragProg = GL_TRUE;
45 FrontWinding = GL_CCW;
46 Xrot = 30;
47 anim = 0;
48 glutIdleFunc(NULL);
49}
50
51
52static void
Brian87002ab2007-12-18 16:21:49 -070053Redisplay(void)
54{
Brian Paulc9122072008-12-18 16:08:42 -070055 const int sections = 20;
Brian Paul1b39b922008-08-15 17:01:35 -060056 int i;
57 float radius = 2;
Brian87002ab2007-12-18 16:21:49 -070058
59 glFrontFace(FrontWinding);
60
Brian Paulc9122072008-12-18 16:08:42 -070061 if (DetermineFacingInFragProg) {
Brian87002ab2007-12-18 16:21:49 -070062 glUniform1i_func(u_fragface, 1);
63 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
64 }
65 else {
66 glUniform1i_func(u_fragface, 0);
67 glEnable(GL_VERTEX_PROGRAM_TWO_SIDE);
68 }
69
Brian Paul1b39b922008-08-15 17:01:35 -060070 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Brian87002ab2007-12-18 16:21:49 -070071
72 glPushMatrix();
Brian Paul1b39b922008-08-15 17:01:35 -060073 glRotatef(Xrot, 1, 0, 0);
Brian87002ab2007-12-18 16:21:49 -070074
Brian Paul1b39b922008-08-15 17:01:35 -060075 /* Draw a tristrip ring */
76 glBegin(GL_TRIANGLE_STRIP);
Brian87002ab2007-12-18 16:21:49 -070077 glColor4fv(Red);
78 glSecondaryColor3fv_func(Green);
Brian Paulc9122072008-12-18 16:08:42 -070079 for (i = 0; i <= sections; i++) {
80 float a = (float) i / (sections) * M_PI * 2.0;
Brian Paul1b39b922008-08-15 17:01:35 -060081 float x = radius * cos(a);
82 float y = radius * sin(a);
83 glVertex3f(x, -1, y);
84 glVertex3f(x, +1, y);
85 }
Brian87002ab2007-12-18 16:21:49 -070086 glEnd();
87
88 glPopMatrix();
89
90 glutSwapBuffers();
91}
92
93
94static void
95Idle(void)
96{
97 int curTime = glutGet(GLUT_ELAPSED_TIME);
98 int dt = curTime - prevTime;
99
100 if (prevTime == 0) {
101 prevTime = curTime;
102 return;
103 }
104 prevTime = curTime;
105
Brian Paul1b39b922008-08-15 17:01:35 -0600106 Xrot += dt * 0.1;
Brian87002ab2007-12-18 16:21:49 -0700107 glutPostRedisplay();
108}
109
110
111static void
112Reshape(int width, int height)
113{
114 float ar = (float) width / height;
115 glViewport(0, 0, width, height);
116 glMatrixMode(GL_PROJECTION);
117 glLoadIdentity();
Brian Paul1b39b922008-08-15 17:01:35 -0600118 glFrustum(-ar, ar, -1, 1, 3, 25);
Brian87002ab2007-12-18 16:21:49 -0700119 glMatrixMode(GL_MODELVIEW);
120 glLoadIdentity();
121 glTranslatef(0, 0, -10);
122}
123
124
125static void
126CleanUp(void)
127{
128 glDeleteShader_func(fragShader);
129 glDeleteShader_func(vertShader);
130 glDeleteProgram_func(program);
131 glutDestroyWindow(win);
132}
133
134
135static void
136Key(unsigned char key, int x, int y)
137{
138 (void) x;
139 (void) y;
140
141 switch(key) {
142 case ' ':
143 case 'a':
144 anim = !anim;
145 if (anim) {
146 prevTime = glutGet(GLUT_ELAPSED_TIME);
147 glutIdleFunc(Idle);
148 }
149 else
150 glutIdleFunc(NULL);
151 break;
152 case 'f':
153 printf("Using frag shader gl_FrontFacing\n");
Brian Paulc9122072008-12-18 16:08:42 -0700154 DetermineFacingInFragProg = GL_TRUE;
Brian87002ab2007-12-18 16:21:49 -0700155 break;
156 case 'v':
157 printf("Using vert shader Two-sided lighting\n");
Brian Paulc9122072008-12-18 16:08:42 -0700158 DetermineFacingInFragProg = GL_FALSE;
Brian87002ab2007-12-18 16:21:49 -0700159 break;
160 case 'r':
Brian Paul1b39b922008-08-15 17:01:35 -0600161 /* reset */
Brian Paulc9122072008-12-18 16:08:42 -0700162 SetDefaults();
Brian87002ab2007-12-18 16:21:49 -0700163 break;
164 case 's':
Brian Paul1b39b922008-08-15 17:01:35 -0600165 Xrot += 5;
166 break;
167 case 'S':
168 Xrot -= 5;
Brian87002ab2007-12-18 16:21:49 -0700169 break;
170 case 'w':
171 if (FrontWinding == GL_CCW) {
172 FrontWinding = GL_CW;
173 printf("FrontFace = GL_CW\n");
174 }
175 else {
176 FrontWinding = GL_CCW;
177 printf("FrontFace = GL_CCW\n");
178 }
179 break;
180 case 27:
181 CleanUp();
182 exit(0);
183 break;
184 }
185 glutPostRedisplay();
186}
187
188
189static void
Brian87002ab2007-12-18 16:21:49 -0700190Init(void)
191{
192 static const char *fragShaderText =
193 "uniform bool fragface; \n"
194 "void main() { \n"
Brian Paulc9122072008-12-18 16:08:42 -0700195#if 1
Brian87002ab2007-12-18 16:21:49 -0700196 " if (!fragface || gl_FrontFacing) { \n"
197 " gl_FragColor = gl_Color; \n"
198 " } \n"
199 " else { \n"
Brian Paulc9122072008-12-18 16:08:42 -0700200 " // note: dim green to help debug \n"
Brian87002ab2007-12-18 16:21:49 -0700201 " gl_FragColor = 0.8 * gl_SecondaryColor; \n"
202 " } \n"
Brian Paul1b39b922008-08-15 17:01:35 -0600203#else
Brian Paulc9122072008-12-18 16:08:42 -0700204 /* DEBUG CODE */
Brian Paul1b39b922008-08-15 17:01:35 -0600205 " bool f = gl_FrontFacing; \n"
206 " if (f) { \n"
207 " gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0); \n"
208 " } \n"
209 " else { \n"
210 " gl_FragColor = vec4(0.0, 1.0, 0.0, 0.0); \n"
211 " } \n"
Brian Paul1b39b922008-08-15 17:01:35 -0600212#endif
Brian87002ab2007-12-18 16:21:49 -0700213 "} \n";
214 static const char *vertShaderText =
215 "uniform bool fragface; \n"
216 "void main() { \n"
217 " gl_FrontColor = gl_Color; \n"
218 " if (fragface) { \n"
219 " // front/back chosen in frag prog \n"
220 " gl_FrontSecondaryColor = gl_SecondaryColor; \n"
221 " } \n"
222 " else { \n"
223 " // front/back chosen in prim setup \n"
224 " gl_BackColor = gl_SecondaryColor; \n"
225 " } \n"
226 " gl_Position = ftransform(); \n"
227 "} \n";
Brian87002ab2007-12-18 16:21:49 -0700228
Brian2dca3372008-04-09 22:28:23 -0600229 if (!ShadersSupported())
Brian87002ab2007-12-18 16:21:49 -0700230 exit(1);
Brian87002ab2007-12-18 16:21:49 -0700231
232 GetExtensionFuncs();
233
Brian2dca3372008-04-09 22:28:23 -0600234 vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
235 fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
236 program = LinkShaders(vertShader, fragShader);
Brian87002ab2007-12-18 16:21:49 -0700237
Brian87002ab2007-12-18 16:21:49 -0700238 glUseProgram_func(program);
239
240 u_fragface = glGetUniformLocation_func(program, "fragface");
241 printf("Uniforms: %d\n", u_fragface);
242
243 /*assert(glGetError() == 0);*/
244
245 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
246
247 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
248
249 assert(glIsProgram_func(program));
250 assert(glIsShader_func(fragShader));
251 assert(glIsShader_func(vertShader));
Brian Paul1b39b922008-08-15 17:01:35 -0600252
253 glEnable(GL_DEPTH_TEST);
Brian Paulc9122072008-12-18 16:08:42 -0700254
255 SetDefaults();
Brian87002ab2007-12-18 16:21:49 -0700256}
257
258
259static void
260ParseOptions(int argc, char *argv[])
261{
262 int i;
263 for (i = 1; i < argc; i++) {
264 if (strcmp(argv[i], "-fs") == 0) {
265 FragProgFile = argv[i+1];
266 }
267 else if (strcmp(argv[i], "-vs") == 0) {
268 VertProgFile = argv[i+1];
269 }
270 }
271}
272
273
274static void
275Usage(void)
276{
277 printf("Keys:\n");
278 printf(" f - do front/back determination in fragment shader\n");
279 printf(" v - do front/back determination in vertex shader\n");
280 printf(" r - reset, show front\n");
281 printf(" a - toggle animation\n");
282 printf(" s - step rotation\n");
283 printf(" w - toggle CW, CCW front-face winding\n");
Brian Paul1b39b922008-08-15 17:01:35 -0600284 printf("NOTE: red = front face, green = back face.\n");
Brian87002ab2007-12-18 16:21:49 -0700285}
286
287
288int
289main(int argc, char *argv[])
290{
291 glutInit(&argc, argv);
292 glutInitWindowPosition( 0, 0);
293 glutInitWindowSize(WinWidth, WinHeight);
Brian Paul1b39b922008-08-15 17:01:35 -0600294 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
Brian87002ab2007-12-18 16:21:49 -0700295 win = glutCreateWindow(argv[0]);
296 glutReshapeFunc(Reshape);
297 glutKeyboardFunc(Key);
298 glutDisplayFunc(Redisplay);
299 if (anim)
300 glutIdleFunc(Idle);
301 ParseOptions(argc, argv);
302 Init();
303 Usage();
304 glutMainLoop();
305 return 0;
306}