merge of glsl-compiler-1 branch
[mesa.git] / progs / glsl / brick.c
1 /**
2 * "Brick" shader demo. Uses the example shaders from chapter 6 of
3 * the OpenGL Shading Language "orange" book.
4 * 10 Jan 2007
5 */
6
7 #include <assert.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <GL/gl.h>
13 #include <GL/glut.h>
14 #include <GL/glext.h>
15 #include "extfuncs.h"
16
17
18 static char *FragProgFile = "CH06-brick.frag.txt";
19 static char *VertProgFile = "CH06-brick.vert.txt";
20
21 /* program/shader objects */
22 static GLuint fragShader;
23 static GLuint vertShader;
24 static GLuint program;
25
26
27 struct uniform_info {
28 const char *name;
29 GLuint size;
30 GLint location;
31 GLfloat value[4];
32 };
33
34 static struct uniform_info Uniforms[] = {
35 /* vert */
36 { "LightPosition", 3, -1, { 0.1, 0.1, 9.0, 0} },
37 /* frag */
38 { "BrickColor", 3, -1, { 0.8, 0.2, 0.2, 0 } },
39 { "MortarColor", 3, -1, { 0.6, 0.6, 0.6, 0 } },
40 { "BrickSize", 2, -1, { 1.0, 0.3, 0, 0 } },
41 { "BrickPct", 2, -1, { 0.9, 0.8, 0, 0 } },
42 { NULL, 0, 0, { 0, 0, 0, 0 } }
43 };
44
45 static GLint win = 0;
46
47
48 static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f;
49
50
51
52
53 static void
54 Redisplay(void)
55 {
56 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
57
58 glPushMatrix();
59 glRotatef(xRot, 1.0f, 0.0f, 0.0f);
60 glRotatef(yRot, 0.0f, 1.0f, 0.0f);
61 glRotatef(zRot, 0.0f, 0.0f, 1.0f);
62
63 glBegin(GL_POLYGON);
64 glTexCoord2f(0, 0); glVertex2f(-2, -2);
65 glTexCoord2f(1, 0); glVertex2f( 2, -2);
66 glTexCoord2f(1, 1); glVertex2f( 2, 2);
67 glTexCoord2f(0, 1); glVertex2f(-2, 2);
68 glEnd();
69
70 glPopMatrix();
71
72 glutSwapBuffers();
73 }
74
75
76 static void
77 Reshape(int width, int height)
78 {
79 glViewport(0, 0, width, height);
80 glMatrixMode(GL_PROJECTION);
81 glLoadIdentity();
82 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
83 glMatrixMode(GL_MODELVIEW);
84 glLoadIdentity();
85 glTranslatef(0.0f, 0.0f, -15.0f);
86 }
87
88
89 static void
90 CleanUp(void)
91 {
92 glDeleteShader_func(fragShader);
93 glDeleteShader_func(vertShader);
94 glDeleteProgram_func(program);
95 glutDestroyWindow(win);
96 }
97
98
99 static void
100 Key(unsigned char key, int x, int y)
101 {
102 (void) x;
103 (void) y;
104
105 switch(key) {
106 case 'z':
107 zRot -= 1.0;
108 break;
109 case 'Z':
110 zRot += 1.0;
111 break;
112 case 27:
113 CleanUp();
114 exit(0);
115 break;
116 }
117 glutPostRedisplay();
118 }
119
120
121 static void
122 SpecialKey(int key, int x, int y)
123 {
124 const GLfloat step = 3.0f;
125
126 (void) x;
127 (void) y;
128
129 switch(key) {
130 case GLUT_KEY_UP:
131 xRot -= step;
132 break;
133 case GLUT_KEY_DOWN:
134 xRot += step;
135 break;
136 case GLUT_KEY_LEFT:
137 yRot -= step;
138 break;
139 case GLUT_KEY_RIGHT:
140 yRot += step;
141 break;
142 }
143 glutPostRedisplay();
144 }
145
146
147
148 static void
149 LoadAndCompileShader(GLuint shader, const char *text)
150 {
151 GLint stat;
152
153 glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
154
155 glCompileShader_func(shader);
156
157 glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
158 if (!stat) {
159 GLchar log[1000];
160 GLsizei len;
161 glGetShaderInfoLog_func(shader, 1000, &len, log);
162 fprintf(stderr, "brick: problem compiling shader: %s\n", log);
163 exit(1);
164 }
165 else {
166 printf("Shader compiled OK\n");
167 }
168 }
169
170
171 /**
172 * Read a shader from a file.
173 */
174 static void
175 ReadShader(GLuint shader, const char *filename)
176 {
177 const int max = 100*1000;
178 int n;
179 char *buffer = (char*) malloc(max);
180 FILE *f = fopen(filename, "r");
181 if (!f) {
182 fprintf(stderr, "brick: Unable to open shader file %s\n", filename);
183 exit(1);
184 }
185
186 n = fread(buffer, 1, max, f);
187 printf("brick: read %d bytes from shader file %s\n", n, filename);
188 if (n > 0) {
189 buffer[n] = 0;
190 LoadAndCompileShader(shader, buffer);
191 }
192
193 fclose(f);
194 free(buffer);
195 }
196
197
198 static void
199 CheckLink(GLuint prog)
200 {
201 GLint stat;
202 glGetProgramiv_func(prog, GL_LINK_STATUS, &stat);
203 if (!stat) {
204 GLchar log[1000];
205 GLsizei len;
206 glGetProgramInfoLog_func(prog, 1000, &len, log);
207 fprintf(stderr, "Linker error:\n%s\n", log);
208 }
209 else {
210 fprintf(stderr, "Link success!\n");
211 }
212 }
213
214
215 static void
216 Init(void)
217 {
218 const char *version;
219 GLint i;
220
221 version = (const char *) glGetString(GL_VERSION);
222 if (version[0] != '2' || version[1] != '.') {
223 printf("Warning: this program expects OpenGL 2.0\n");
224 /*exit(1);*/
225 }
226
227 GetExtensionFuncs();
228
229 vertShader = glCreateShader_func(GL_VERTEX_SHADER);
230 ReadShader(vertShader, VertProgFile);
231
232 fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
233 ReadShader(fragShader, FragProgFile);
234
235 program = glCreateProgram_func();
236 glAttachShader_func(program, fragShader);
237 glAttachShader_func(program, vertShader);
238 glLinkProgram_func(program);
239 CheckLink(program);
240 glUseProgram_func(program);
241
242 for (i = 0; Uniforms[i].name; i++) {
243 Uniforms[i].location
244 = glGetUniformLocation_func(program, Uniforms[i].name);
245 printf("Uniform %s location: %d\n", Uniforms[i].name,
246 Uniforms[i].location);
247 switch (Uniforms[i].size) {
248 case 1:
249 glUniform1fv_func(Uniforms[i].location, 1, Uniforms[i].value);
250 break;
251 case 2:
252 glUniform2fv_func(Uniforms[i].location, 1, Uniforms[i].value);
253 break;
254 case 3:
255 glUniform3fv_func(Uniforms[i].location, 1, Uniforms[i].value);
256 break;
257 case 4:
258 glUniform4fv_func(Uniforms[i].location, 1, Uniforms[i].value);
259 break;
260 default:
261 abort();
262 }
263 }
264
265 assert(glGetError() == 0);
266
267 glClearColor(0.4f, 0.4f, 0.8f, 0.0f);
268
269 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
270
271 assert(glIsProgram_func(program));
272 assert(glIsShader_func(fragShader));
273 assert(glIsShader_func(vertShader));
274
275 glColor3f(1, 0, 0);
276 }
277
278
279 static void
280 ParseOptions(int argc, char *argv[])
281 {
282 int i;
283 for (i = 1; i < argc; i++) {
284 if (strcmp(argv[i], "-fs") == 0) {
285 FragProgFile = argv[i+1];
286 }
287 else if (strcmp(argv[i], "-vs") == 0) {
288 VertProgFile = argv[i+1];
289 }
290 }
291 }
292
293
294 int
295 main(int argc, char *argv[])
296 {
297 glutInit(&argc, argv);
298 glutInitWindowPosition( 0, 0);
299 glutInitWindowSize(400, 400);
300 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
301 win = glutCreateWindow(argv[0]);
302 glutReshapeFunc(Reshape);
303 glutKeyboardFunc(Key);
304 glutSpecialFunc(SpecialKey);
305 glutDisplayFunc(Redisplay);
306 ParseOptions(argc, argv);
307 Init();
308 glutMainLoop();
309 return 0;
310 }
311