blob: 77977be536f4f3d8785afd194b37b4a49279b52b [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;
29static GLboolean anim = 0*GL_TRUE;
30static GLboolean DetermineInFragProg = GL_TRUE;
31static GLfloat Yrot = 0.0f;
32static GLint u_fragface;
33static GLenum FrontWinding = GL_CCW;
34static int prevTime = 0;
35
36
37static const GLfloat Red[4] = {1, 0, 0, 0};
38static const GLfloat Green[4] = {0, 1, 0, 0};
39
40
41static void
42Redisplay(void)
43{
44 float xmin = -1, xmax = 1, ymin = -1, ymax = 1;
45
46 glFrontFace(FrontWinding);
47
48 if (DetermineInFragProg) {
49 glUniform1i_func(u_fragface, 1);
50 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE);
51 }
52 else {
53 glUniform1i_func(u_fragface, 0);
54 glEnable(GL_VERTEX_PROGRAM_TWO_SIDE);
55 }
56
57 glClear(GL_COLOR_BUFFER_BIT);
58
59 glPushMatrix();
60 glRotatef(Yrot, 0, 1, 0);
61
62 glBegin(GL_POLYGON);
63 glColor4fv(Red);
64 glSecondaryColor3fv_func(Green);
65 glVertex2f(xmin, ymin);
66 glVertex2f(xmax, ymin);
67 glVertex2f(xmax, ymax);
68 glVertex2f(xmin, ymax);
69 glEnd();
70
71 glPopMatrix();
72
73 glutSwapBuffers();
74}
75
76
77static void
78Idle(void)
79{
80 int curTime = glutGet(GLUT_ELAPSED_TIME);
81 int dt = curTime - prevTime;
82
83 if (prevTime == 0) {
84 prevTime = curTime;
85 return;
86 }
87 prevTime = curTime;
88
89 Yrot += dt * 0.1;
90 glutPostRedisplay();
91}
92
93
94static void
95Reshape(int width, int height)
96{
97 float ar = (float) width / height;
98 glViewport(0, 0, width, height);
99 glMatrixMode(GL_PROJECTION);
100 glLoadIdentity();
101 glFrustum(-ar, ar, -1, 1, 5, 15);
102 glMatrixMode(GL_MODELVIEW);
103 glLoadIdentity();
104 glTranslatef(0, 0, -10);
105}
106
107
108static void
109CleanUp(void)
110{
111 glDeleteShader_func(fragShader);
112 glDeleteShader_func(vertShader);
113 glDeleteProgram_func(program);
114 glutDestroyWindow(win);
115}
116
117
118static void
119Key(unsigned char key, int x, int y)
120{
121 (void) x;
122 (void) y;
123
124 switch(key) {
125 case ' ':
126 case 'a':
127 anim = !anim;
128 if (anim) {
129 prevTime = glutGet(GLUT_ELAPSED_TIME);
130 glutIdleFunc(Idle);
131 }
132 else
133 glutIdleFunc(NULL);
134 break;
135 case 'f':
136 printf("Using frag shader gl_FrontFacing\n");
137 DetermineInFragProg = GL_TRUE;
138 break;
139 case 'v':
140 printf("Using vert shader Two-sided lighting\n");
141 DetermineInFragProg = GL_FALSE;
142 break;
143 case 'r':
144 Yrot = 0;
145 anim = 0;
146 glutIdleFunc(NULL);
147 break;
148 case 's':
149 Yrot += 5;
150 break;
151 case 'w':
152 if (FrontWinding == GL_CCW) {
153 FrontWinding = GL_CW;
154 printf("FrontFace = GL_CW\n");
155 }
156 else {
157 FrontWinding = GL_CCW;
158 printf("FrontFace = GL_CCW\n");
159 }
160 break;
161 case 27:
162 CleanUp();
163 exit(0);
164 break;
165 }
166 glutPostRedisplay();
167}
168
169
170static void
Brian87002ab2007-12-18 16:21:49 -0700171Init(void)
172{
173 static const char *fragShaderText =
174 "uniform bool fragface; \n"
175 "void main() { \n"
176 " if (!fragface || gl_FrontFacing) { \n"
177 " gl_FragColor = gl_Color; \n"
178 " } \n"
179 " else { \n"
180 " gl_FragColor = 0.8 * gl_SecondaryColor; \n"
181 " } \n"
182 "} \n";
183 static const char *vertShaderText =
184 "uniform bool fragface; \n"
185 "void main() { \n"
186 " gl_FrontColor = gl_Color; \n"
187 " if (fragface) { \n"
188 " // front/back chosen in frag prog \n"
189 " gl_FrontSecondaryColor = gl_SecondaryColor; \n"
190 " } \n"
191 " else { \n"
192 " // front/back chosen in prim setup \n"
193 " gl_BackColor = gl_SecondaryColor; \n"
194 " } \n"
195 " gl_Position = ftransform(); \n"
196 "} \n";
Brian87002ab2007-12-18 16:21:49 -0700197
Brian2dca3372008-04-09 22:28:23 -0600198 if (!ShadersSupported())
Brian87002ab2007-12-18 16:21:49 -0700199 exit(1);
Brian87002ab2007-12-18 16:21:49 -0700200
201 GetExtensionFuncs();
202
Brian2dca3372008-04-09 22:28:23 -0600203 vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
204 fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
205 program = LinkShaders(vertShader, fragShader);
Brian87002ab2007-12-18 16:21:49 -0700206
Brian87002ab2007-12-18 16:21:49 -0700207 glUseProgram_func(program);
208
209 u_fragface = glGetUniformLocation_func(program, "fragface");
210 printf("Uniforms: %d\n", u_fragface);
211
212 /*assert(glGetError() == 0);*/
213
214 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
215
216 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
217
218 assert(glIsProgram_func(program));
219 assert(glIsShader_func(fragShader));
220 assert(glIsShader_func(vertShader));
221}
222
223
224static void
225ParseOptions(int argc, char *argv[])
226{
227 int i;
228 for (i = 1; i < argc; i++) {
229 if (strcmp(argv[i], "-fs") == 0) {
230 FragProgFile = argv[i+1];
231 }
232 else if (strcmp(argv[i], "-vs") == 0) {
233 VertProgFile = argv[i+1];
234 }
235 }
236}
237
238
239static void
240Usage(void)
241{
242 printf("Keys:\n");
243 printf(" f - do front/back determination in fragment shader\n");
244 printf(" v - do front/back determination in vertex shader\n");
245 printf(" r - reset, show front\n");
246 printf(" a - toggle animation\n");
247 printf(" s - step rotation\n");
248 printf(" w - toggle CW, CCW front-face winding\n");
249}
250
251
252int
253main(int argc, char *argv[])
254{
255 glutInit(&argc, argv);
256 glutInitWindowPosition( 0, 0);
257 glutInitWindowSize(WinWidth, WinHeight);
258 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
259 win = glutCreateWindow(argv[0]);
260 glutReshapeFunc(Reshape);
261 glutKeyboardFunc(Key);
262 glutDisplayFunc(Redisplay);
263 if (anim)
264 glutIdleFunc(Idle);
265 ParseOptions(argc, argv);
266 Init();
267 Usage();
268 glutMainLoop();
269 return 0;
270}