Merge branch '7.8'
[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/glew.h>
16 #include <GL/glut.h>
17 #include "shaderutil.h"
18
19 #ifndef M_PI
20 #define M_PI 3.1415926535
21 #endif
22
23 static GLint WinWidth = 300, WinHeight = 300;
24 static char *FragProgFile = NULL;
25 static char *VertProgFile = NULL;
26 static GLuint fragShader;
27 static GLuint vertShader;
28 static GLuint program;
29 static GLint win = 0;
30 static GLboolean anim;
31 static GLboolean DetermineFacingInFragProg;
32 static GLfloat Xrot;
33 static GLint u_fragface;
34 static GLenum FrontWinding;
35 static int prevTime = 0;
36
37
38 static const GLfloat Red[4] = {1, 0, 0, 1};
39 static const GLfloat Green[4] = {0, 1, 0, 0};
40
41
42 static void
43 SetDefaults(void)
44 {
45 DetermineFacingInFragProg = GL_TRUE;
46 FrontWinding = GL_CCW;
47 Xrot = 30;
48 anim = 0;
49 glutIdleFunc(NULL);
50 }
51
52
53 static void
54 Redisplay(void)
55 {
56 const int sections = 20;
57 int i;
58 float radius = 2;
59
60 glFrontFace(FrontWinding);
61
62 if (DetermineFacingInFragProg) {
63 glUniform1i(u_fragface, 1);
64 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
65 }
66 else {
67 glUniform1i(u_fragface, 0);
68 glEnable(GL_VERTEX_PROGRAM_TWO_SIDE);
69 }
70
71 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
72
73 glPushMatrix();
74 glRotatef(Xrot, 1, 0, 0);
75
76 /* Draw a tristrip ring */
77 glBegin(GL_TRIANGLE_STRIP);
78 glColor4fv(Red);
79 glSecondaryColor3fv(Green);
80 for (i = 0; i <= sections; i++) {
81 float a = (float) i / (sections) * M_PI * 2.0;
82 float x = radius * cos(a);
83 float y = radius * sin(a);
84 glVertex3f(x, -1, y);
85 glVertex3f(x, +1, y);
86 }
87 glEnd();
88
89 glPopMatrix();
90
91 glutSwapBuffers();
92 }
93
94
95 static void
96 Idle(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
107 Xrot += dt * 0.1;
108 glutPostRedisplay();
109 }
110
111
112 static void
113 Reshape(int width, int height)
114 {
115 float ar = (float) width / height;
116 glViewport(0, 0, width, height);
117 glMatrixMode(GL_PROJECTION);
118 glLoadIdentity();
119 glFrustum(-ar, ar, -1, 1, 3, 25);
120 glMatrixMode(GL_MODELVIEW);
121 glLoadIdentity();
122 glTranslatef(0, 0, -10);
123 }
124
125
126 static void
127 CleanUp(void)
128 {
129 glDeleteShader(fragShader);
130 glDeleteShader(vertShader);
131 glDeleteProgram(program);
132 glutDestroyWindow(win);
133 }
134
135
136 static void
137 Key(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");
155 DetermineFacingInFragProg = GL_TRUE;
156 break;
157 case 'v':
158 printf("Using vert shader Two-sided lighting\n");
159 DetermineFacingInFragProg = GL_FALSE;
160 break;
161 case 'r':
162 /* reset */
163 SetDefaults();
164 break;
165 case 's':
166 Xrot += 5;
167 break;
168 case 'S':
169 Xrot -= 5;
170 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
190 static void
191 Init(void)
192 {
193 static const char *fragShaderText =
194 "uniform bool fragface; \n"
195 "void main() { \n"
196 #if 1
197 " if (!fragface || gl_FrontFacing) { \n"
198 " gl_FragColor = gl_Color; \n"
199 " } \n"
200 " else { \n"
201 " // note: dim green to help debug \n"
202 " gl_FragColor = 0.8 * gl_SecondaryColor; \n"
203 " } \n"
204 #else
205 /* DEBUG CODE */
206 " 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"
213 #endif
214 "} \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";
229
230 if (!ShadersSupported())
231 exit(1);
232
233 vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
234 fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
235 program = LinkShaders(vertShader, fragShader);
236
237 glUseProgram(program);
238
239 u_fragface = glGetUniformLocation(program, "fragface");
240 printf("Uniforms: %d\n", u_fragface);
241
242 /*assert(glGetError() == 0);*/
243
244 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
245
246 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
247
248 assert(glIsProgram(program));
249 assert(glIsShader(fragShader));
250 assert(glIsShader(vertShader));
251
252 glEnable(GL_DEPTH_TEST);
253
254 SetDefaults();
255 }
256
257
258 static void
259 ParseOptions(int argc, char *argv[])
260 {
261 int i;
262 for (i = 1; i < argc; i++) {
263 if (strcmp(argv[i], "-fs") == 0) {
264 FragProgFile = argv[i+1];
265 }
266 else if (strcmp(argv[i], "-vs") == 0) {
267 VertProgFile = argv[i+1];
268 }
269 }
270 }
271
272
273 static void
274 Usage(void)
275 {
276 printf("Keys:\n");
277 printf(" f - do front/back determination in fragment shader\n");
278 printf(" v - do front/back determination in vertex shader\n");
279 printf(" r - reset, show front\n");
280 printf(" a - toggle animation\n");
281 printf(" s - step rotation\n");
282 printf(" w - toggle CW, CCW front-face winding\n");
283 printf("NOTE: red = front face, green = back face.\n");
284 }
285
286
287 int
288 main(int argc, char *argv[])
289 {
290 glutInit(&argc, argv);
291 glutInitWindowSize(WinWidth, WinHeight);
292 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
293 win = glutCreateWindow(argv[0]);
294 glewInit();
295 glutReshapeFunc(Reshape);
296 glutKeyboardFunc(Key);
297 glutDisplayFunc(Redisplay);
298 if (anim)
299 glutIdleFunc(Idle);
300 ParseOptions(argc, argv);
301 Init();
302 Usage();
303 glutMainLoop();
304 return 0;
305 }