blob: b6c1b477dde70de4fc47ec27caec7616d13b0bb3 [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/glut.h>
Brian2dca3372008-04-09 22:28:23 -060017#include "shaderutil.h"
Brian87002ab2007-12-18 16:21:49 -070018
19
Brian87002ab2007-12-18 16:21:49 -070020static GLint WinWidth = 300, WinHeight = 300;
21static char *FragProgFile = NULL;
22static char *VertProgFile = NULL;
23static GLuint fragShader;
24static GLuint vertShader;
25static GLuint program;
26static GLint win = 0;
Brian Paulc9122072008-12-18 16:08:42 -070027static GLboolean anim;
28static GLboolean DetermineFacingInFragProg;
29static GLfloat Xrot;
Brian87002ab2007-12-18 16:21:49 -070030static GLint u_fragface;
Brian Paulc9122072008-12-18 16:08:42 -070031static GLenum FrontWinding;
Brian87002ab2007-12-18 16:21:49 -070032static int prevTime = 0;
33
34
Brian Paulc9122072008-12-18 16:08:42 -070035static const GLfloat Red[4] = {1, 0, 0, 1};
Brian87002ab2007-12-18 16:21:49 -070036static const GLfloat Green[4] = {0, 1, 0, 0};
37
38
39static void
Brian Paulc9122072008-12-18 16:08:42 -070040SetDefaults(void)
41{
42 DetermineFacingInFragProg = GL_TRUE;
43 FrontWinding = GL_CCW;
44 Xrot = 30;
45 anim = 0;
46 glutIdleFunc(NULL);
47}
48
49
50static void
Brian87002ab2007-12-18 16:21:49 -070051Redisplay(void)
52{
Brian Paulc9122072008-12-18 16:08:42 -070053 const int sections = 20;
Brian Paul1b39b922008-08-15 17:01:35 -060054 int i;
55 float radius = 2;
Brian87002ab2007-12-18 16:21:49 -070056
57 glFrontFace(FrontWinding);
58
Brian Paulc9122072008-12-18 16:08:42 -070059 if (DetermineFacingInFragProg) {
Brian Paulee0b1bc2009-07-17 13:23:11 -060060 glUniform1i(u_fragface, 1);
Brian87002ab2007-12-18 16:21:49 -070061 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
62 }
63 else {
Brian Paulee0b1bc2009-07-17 13:23:11 -060064 glUniform1i(u_fragface, 0);
Brian87002ab2007-12-18 16:21:49 -070065 glEnable(GL_VERTEX_PROGRAM_TWO_SIDE);
66 }
67
Brian Paul1b39b922008-08-15 17:01:35 -060068 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Brian87002ab2007-12-18 16:21:49 -070069
70 glPushMatrix();
Brian Paul1b39b922008-08-15 17:01:35 -060071 glRotatef(Xrot, 1, 0, 0);
Brian87002ab2007-12-18 16:21:49 -070072
Brian Paul1b39b922008-08-15 17:01:35 -060073 /* Draw a tristrip ring */
74 glBegin(GL_TRIANGLE_STRIP);
Brian87002ab2007-12-18 16:21:49 -070075 glColor4fv(Red);
Brian Paulee0b1bc2009-07-17 13:23:11 -060076 glSecondaryColor3fv(Green);
Brian Paulc9122072008-12-18 16:08:42 -070077 for (i = 0; i <= sections; i++) {
78 float a = (float) i / (sections) * M_PI * 2.0;
Brian Paul1b39b922008-08-15 17:01:35 -060079 float x = radius * cos(a);
80 float y = radius * sin(a);
81 glVertex3f(x, -1, y);
82 glVertex3f(x, +1, y);
83 }
Brian87002ab2007-12-18 16:21:49 -070084 glEnd();
85
86 glPopMatrix();
87
88 glutSwapBuffers();
89}
90
91
92static void
93Idle(void)
94{
95 int curTime = glutGet(GLUT_ELAPSED_TIME);
96 int dt = curTime - prevTime;
97
98 if (prevTime == 0) {
99 prevTime = curTime;
100 return;
101 }
102 prevTime = curTime;
103
Brian Paul1b39b922008-08-15 17:01:35 -0600104 Xrot += dt * 0.1;
Brian87002ab2007-12-18 16:21:49 -0700105 glutPostRedisplay();
106}
107
108
109static void
110Reshape(int width, int height)
111{
112 float ar = (float) width / height;
113 glViewport(0, 0, width, height);
114 glMatrixMode(GL_PROJECTION);
115 glLoadIdentity();
Brian Paul1b39b922008-08-15 17:01:35 -0600116 glFrustum(-ar, ar, -1, 1, 3, 25);
Brian87002ab2007-12-18 16:21:49 -0700117 glMatrixMode(GL_MODELVIEW);
118 glLoadIdentity();
119 glTranslatef(0, 0, -10);
120}
121
122
123static void
124CleanUp(void)
125{
Brian Paulee0b1bc2009-07-17 13:23:11 -0600126 glDeleteShader(fragShader);
127 glDeleteShader(vertShader);
128 glDeleteProgram(program);
Brian87002ab2007-12-18 16:21:49 -0700129 glutDestroyWindow(win);
130}
131
132
133static void
134Key(unsigned char key, int x, int y)
135{
136 (void) x;
137 (void) y;
138
139 switch(key) {
140 case ' ':
141 case 'a':
142 anim = !anim;
143 if (anim) {
144 prevTime = glutGet(GLUT_ELAPSED_TIME);
145 glutIdleFunc(Idle);
146 }
147 else
148 glutIdleFunc(NULL);
149 break;
150 case 'f':
151 printf("Using frag shader gl_FrontFacing\n");
Brian Paulc9122072008-12-18 16:08:42 -0700152 DetermineFacingInFragProg = GL_TRUE;
Brian87002ab2007-12-18 16:21:49 -0700153 break;
154 case 'v':
155 printf("Using vert shader Two-sided lighting\n");
Brian Paulc9122072008-12-18 16:08:42 -0700156 DetermineFacingInFragProg = GL_FALSE;
Brian87002ab2007-12-18 16:21:49 -0700157 break;
158 case 'r':
Brian Paul1b39b922008-08-15 17:01:35 -0600159 /* reset */
Brian Paulc9122072008-12-18 16:08:42 -0700160 SetDefaults();
Brian87002ab2007-12-18 16:21:49 -0700161 break;
162 case 's':
Brian Paul1b39b922008-08-15 17:01:35 -0600163 Xrot += 5;
164 break;
165 case 'S':
166 Xrot -= 5;
Brian87002ab2007-12-18 16:21:49 -0700167 break;
168 case 'w':
169 if (FrontWinding == GL_CCW) {
170 FrontWinding = GL_CW;
171 printf("FrontFace = GL_CW\n");
172 }
173 else {
174 FrontWinding = GL_CCW;
175 printf("FrontFace = GL_CCW\n");
176 }
177 break;
178 case 27:
179 CleanUp();
180 exit(0);
181 break;
182 }
183 glutPostRedisplay();
184}
185
186
187static void
Brian87002ab2007-12-18 16:21:49 -0700188Init(void)
189{
190 static const char *fragShaderText =
191 "uniform bool fragface; \n"
192 "void main() { \n"
Brian Paulc9122072008-12-18 16:08:42 -0700193#if 1
Brian87002ab2007-12-18 16:21:49 -0700194 " if (!fragface || gl_FrontFacing) { \n"
195 " gl_FragColor = gl_Color; \n"
196 " } \n"
197 " else { \n"
Brian Paulc9122072008-12-18 16:08:42 -0700198 " // note: dim green to help debug \n"
Brian87002ab2007-12-18 16:21:49 -0700199 " gl_FragColor = 0.8 * gl_SecondaryColor; \n"
200 " } \n"
Brian Paul1b39b922008-08-15 17:01:35 -0600201#else
Brian Paulc9122072008-12-18 16:08:42 -0700202 /* DEBUG CODE */
Brian Paul1b39b922008-08-15 17:01:35 -0600203 " bool f = gl_FrontFacing; \n"
204 " if (f) { \n"
205 " gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0); \n"
206 " } \n"
207 " else { \n"
208 " gl_FragColor = vec4(0.0, 1.0, 0.0, 0.0); \n"
209 " } \n"
Brian Paul1b39b922008-08-15 17:01:35 -0600210#endif
Brian87002ab2007-12-18 16:21:49 -0700211 "} \n";
212 static const char *vertShaderText =
213 "uniform bool fragface; \n"
214 "void main() { \n"
215 " gl_FrontColor = gl_Color; \n"
216 " if (fragface) { \n"
217 " // front/back chosen in frag prog \n"
218 " gl_FrontSecondaryColor = gl_SecondaryColor; \n"
219 " } \n"
220 " else { \n"
221 " // front/back chosen in prim setup \n"
222 " gl_BackColor = gl_SecondaryColor; \n"
223 " } \n"
224 " gl_Position = ftransform(); \n"
225 "} \n";
Brian87002ab2007-12-18 16:21:49 -0700226
Brian2dca3372008-04-09 22:28:23 -0600227 if (!ShadersSupported())
Brian87002ab2007-12-18 16:21:49 -0700228 exit(1);
Brian87002ab2007-12-18 16:21:49 -0700229
Brian2dca3372008-04-09 22:28:23 -0600230 vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
231 fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
232 program = LinkShaders(vertShader, fragShader);
Brian87002ab2007-12-18 16:21:49 -0700233
Brian Paulee0b1bc2009-07-17 13:23:11 -0600234 glUseProgram(program);
Brian87002ab2007-12-18 16:21:49 -0700235
Brian Paulee0b1bc2009-07-17 13:23:11 -0600236 u_fragface = glGetUniformLocation(program, "fragface");
Brian87002ab2007-12-18 16:21:49 -0700237 printf("Uniforms: %d\n", u_fragface);
238
239 /*assert(glGetError() == 0);*/
240
241 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
242
243 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
244
Brian Paulee0b1bc2009-07-17 13:23:11 -0600245 assert(glIsProgram(program));
246 assert(glIsShader(fragShader));
247 assert(glIsShader(vertShader));
Brian Paul1b39b922008-08-15 17:01:35 -0600248
249 glEnable(GL_DEPTH_TEST);
Brian Paulc9122072008-12-18 16:08:42 -0700250
251 SetDefaults();
Brian87002ab2007-12-18 16:21:49 -0700252}
253
254
255static void
256ParseOptions(int argc, char *argv[])
257{
258 int i;
259 for (i = 1; i < argc; i++) {
260 if (strcmp(argv[i], "-fs") == 0) {
261 FragProgFile = argv[i+1];
262 }
263 else if (strcmp(argv[i], "-vs") == 0) {
264 VertProgFile = argv[i+1];
265 }
266 }
267}
268
269
270static void
271Usage(void)
272{
273 printf("Keys:\n");
274 printf(" f - do front/back determination in fragment shader\n");
275 printf(" v - do front/back determination in vertex shader\n");
276 printf(" r - reset, show front\n");
277 printf(" a - toggle animation\n");
278 printf(" s - step rotation\n");
279 printf(" w - toggle CW, CCW front-face winding\n");
Brian Paul1b39b922008-08-15 17:01:35 -0600280 printf("NOTE: red = front face, green = back face.\n");
Brian87002ab2007-12-18 16:21:49 -0700281}
282
283
284int
285main(int argc, char *argv[])
286{
287 glutInit(&argc, argv);
288 glutInitWindowPosition( 0, 0);
289 glutInitWindowSize(WinWidth, WinHeight);
Brian Paul1b39b922008-08-15 17:01:35 -0600290 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
Brian87002ab2007-12-18 16:21:49 -0700291 win = glutCreateWindow(argv[0]);
Keith Whitwellb799af92009-06-29 14:13:58 +0100292 glewInit();
Brian87002ab2007-12-18 16:21:49 -0700293 glutReshapeFunc(Reshape);
294 glutKeyboardFunc(Key);
295 glutDisplayFunc(Redisplay);
296 if (anim)
297 glutIdleFunc(Idle);
298 ParseOptions(argc, argv);
299 Init();
300 Usage();
301 glutMainLoop();
302 return 0;
303}