06488bd1759d74187dd2143beef5cdd00acc611e
[mesa.git] / progs / glsl / twoside.c
1 /**
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"
19 #include "shaderutil.h"
20
21
22 static GLint WinWidth = 300, WinHeight = 300;
23 static char *FragProgFile = NULL;
24 static char *VertProgFile = NULL;
25 static GLuint fragShader;
26 static GLuint vertShader;
27 static GLuint program;
28 static GLint win = 0;
29 static GLboolean anim;
30 static GLboolean DetermineFacingInFragProg;
31 static GLfloat Xrot;
32 static GLint u_fragface;
33 static GLenum FrontWinding;
34 static int prevTime = 0;
35
36
37 static const GLfloat Red[4] = {1, 0, 0, 1};
38 static const GLfloat Green[4] = {0, 1, 0, 0};
39
40
41 static void
42 SetDefaults(void)
43 {
44 DetermineFacingInFragProg = GL_TRUE;
45 FrontWinding = GL_CCW;
46 Xrot = 30;
47 anim = 0;
48 glutIdleFunc(NULL);
49 }
50
51
52 static void
53 Redisplay(void)
54 {
55 const int sections = 20;
56 int i;
57 float radius = 2;
58
59 glFrontFace(FrontWinding);
60
61 if (DetermineFacingInFragProg) {
62 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
70 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
71
72 glPushMatrix();
73 glRotatef(Xrot, 1, 0, 0);
74
75 /* Draw a tristrip ring */
76 glBegin(GL_TRIANGLE_STRIP);
77 glColor4fv(Red);
78 glSecondaryColor3fv_func(Green);
79 for (i = 0; i <= sections; i++) {
80 float a = (float) i / (sections) * M_PI * 2.0;
81 float x = radius * cos(a);
82 float y = radius * sin(a);
83 glVertex3f(x, -1, y);
84 glVertex3f(x, +1, y);
85 }
86 glEnd();
87
88 glPopMatrix();
89
90 glutSwapBuffers();
91 }
92
93
94 static void
95 Idle(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
106 Xrot += dt * 0.1;
107 glutPostRedisplay();
108 }
109
110
111 static void
112 Reshape(int width, int height)
113 {
114 float ar = (float) width / height;
115 glViewport(0, 0, width, height);
116 glMatrixMode(GL_PROJECTION);
117 glLoadIdentity();
118 glFrustum(-ar, ar, -1, 1, 3, 25);
119 glMatrixMode(GL_MODELVIEW);
120 glLoadIdentity();
121 glTranslatef(0, 0, -10);
122 }
123
124
125 static void
126 CleanUp(void)
127 {
128 glDeleteShader_func(fragShader);
129 glDeleteShader_func(vertShader);
130 glDeleteProgram_func(program);
131 glutDestroyWindow(win);
132 }
133
134
135 static void
136 Key(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");
154 DetermineFacingInFragProg = GL_TRUE;
155 break;
156 case 'v':
157 printf("Using vert shader Two-sided lighting\n");
158 DetermineFacingInFragProg = GL_FALSE;
159 break;
160 case 'r':
161 /* reset */
162 SetDefaults();
163 break;
164 case 's':
165 Xrot += 5;
166 break;
167 case 'S':
168 Xrot -= 5;
169 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
189 static void
190 Init(void)
191 {
192 static const char *fragShaderText =
193 "uniform bool fragface; \n"
194 "void main() { \n"
195 #if 1
196 " if (!fragface || gl_FrontFacing) { \n"
197 " gl_FragColor = gl_Color; \n"
198 " } \n"
199 " else { \n"
200 " // note: dim green to help debug \n"
201 " gl_FragColor = 0.8 * gl_SecondaryColor; \n"
202 " } \n"
203 #else
204 /* DEBUG CODE */
205 " 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"
212 #endif
213 "} \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";
228
229 if (!ShadersSupported())
230 exit(1);
231
232 GetExtensionFuncs();
233
234 vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
235 fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
236 program = LinkShaders(vertShader, fragShader);
237
238 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));
252
253 glEnable(GL_DEPTH_TEST);
254
255 SetDefaults();
256 }
257
258
259 static void
260 ParseOptions(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
274 static void
275 Usage(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");
284 printf("NOTE: red = front face, green = back face.\n");
285 }
286
287
288 int
289 main(int argc, char *argv[])
290 {
291 glutInit(&argc, argv);
292 glutInitWindowPosition( 0, 0);
293 glutInitWindowSize(WinWidth, WinHeight);
294 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
295 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 }