Replace duplicated code with new shaderutil.c functions
[mesa.git] / progs / glsl / mandelbrot.c
1 /**
2 * "Mandelbrot" shader demo. Uses the example shaders from
3 * chapter 15 (or 18) of the OpenGL Shading Language "orange" book.
4 * 15 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 #include "shaderutil.h"
17
18
19 static char *FragProgFile = "CH18-mandel.frag.txt";
20 static char *VertProgFile = "CH18-mandel.vert.txt";
21
22 /* program/shader objects */
23 static GLuint fragShader;
24 static GLuint vertShader;
25 static GLuint program;
26
27
28 static struct uniform_info Uniforms[] = {
29 /* vert */
30 { "LightPosition", 3, GL_FLOAT, { 0.1, 0.1, 9.0, 0}, -1 },
31 { "SpecularContribution", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
32 { "DiffuseContribution", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
33 { "Shininess", 1, GL_FLOAT, { 20.0, 0, 0, 0 }, -1 },
34 /* frag */
35 { "MaxIterations", 1, GL_FLOAT, { 12, 0, 0, 0 }, -1 },
36 { "Zoom", 1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 },
37 { "Xcenter", 1, GL_FLOAT, { -1.5, 0, 0, 0 }, -1 },
38 { "Ycenter", 1, GL_FLOAT, { .005, 0, 0, 0 }, -1 },
39 { "InnerColor", 3, GL_FLOAT, { 1, 0, 0, 0 }, -1 },
40 { "OuterColor1", 3, GL_FLOAT, { 0, 1, 0, 0 }, -1 },
41 { "OuterColor2", 3, GL_FLOAT, { 0, 0, 1, 0 }, -1 },
42 END_OF_UNIFORMS
43 };
44
45 static GLint win = 0;
46
47 static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f;
48
49 static GLint uZoom, uXcenter, uYcenter;
50 static GLfloat zoom = 1.0, xCenter = -1.5, yCenter = 0.0;
51
52
53 static void
54 Redisplay(void)
55 {
56 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
57
58 /* set interactive uniform parameters */
59 glUniform1fv_func(uZoom, 1, &zoom);
60 glUniform1fv_func(uXcenter, 1, &xCenter);
61 glUniform1fv_func(uYcenter, 1, &yCenter);
62
63 glPushMatrix();
64 glRotatef(xRot, 1.0f, 0.0f, 0.0f);
65 glRotatef(yRot, 0.0f, 1.0f, 0.0f);
66 glRotatef(zRot, 0.0f, 0.0f, 1.0f);
67
68 glBegin(GL_POLYGON);
69 glTexCoord2f(0, 0); glVertex2f(-1, -1);
70 glTexCoord2f(1, 0); glVertex2f( 1, -1);
71 glTexCoord2f(1, 1); glVertex2f( 1, 1);
72 glTexCoord2f(0, 1); glVertex2f(-1, 1);
73 glEnd();
74
75 glPopMatrix();
76
77 glFinish();
78 glFlush();
79 glutSwapBuffers();
80 }
81
82
83 static void
84 Reshape(int width, int height)
85 {
86 glViewport(0, 0, width, height);
87 glMatrixMode(GL_PROJECTION);
88 glLoadIdentity();
89 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
90 glMatrixMode(GL_MODELVIEW);
91 glLoadIdentity();
92 glTranslatef(0.0f, 0.0f, -6.0f);
93 }
94
95
96 static void
97 CleanUp(void)
98 {
99 glDeleteShader_func(fragShader);
100 glDeleteShader_func(vertShader);
101 glDeleteProgram_func(program);
102 glutDestroyWindow(win);
103 }
104
105
106 static void
107 Key(unsigned char key, int x, int y)
108 {
109 (void) x;
110 (void) y;
111
112 switch(key) {
113 case 'z':
114 zoom *= 0.9;
115 break;
116 case 'Z':
117 zoom /= 0.9;
118 break;
119 case 27:
120 CleanUp();
121 exit(0);
122 break;
123 }
124 glutPostRedisplay();
125 }
126
127
128 static void
129 SpecialKey(int key, int x, int y)
130 {
131 const GLfloat step = 0.1 * zoom;
132
133 (void) x;
134 (void) y;
135
136 switch(key) {
137 case GLUT_KEY_UP:
138 yCenter += step;
139 break;
140 case GLUT_KEY_DOWN:
141 yCenter -= step;
142 break;
143 case GLUT_KEY_LEFT:
144 xCenter -= step;
145 break;
146 case GLUT_KEY_RIGHT:
147 xCenter += step;
148 break;
149 }
150 glutPostRedisplay();
151 }
152
153
154 static void
155 Init(void)
156 {
157 GLint i;
158
159 if (!ShadersSupported())
160 exit(1);
161
162 GetExtensionFuncs();
163
164 vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
165 fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
166 program = LinkShaders(vertShader, fragShader);
167
168 glUseProgram_func(program);
169
170 for (i = 0; Uniforms[i].name; i++) {
171 Uniforms[i].location
172 = glGetUniformLocation_func(program, Uniforms[i].name);
173 printf("Uniform %s location: %d\n", Uniforms[i].name,
174 Uniforms[i].location);
175 switch (Uniforms[i].size) {
176 case 1:
177 glUniform1fv_func(Uniforms[i].location, 1, Uniforms[i].value);
178 break;
179 case 2:
180 glUniform2fv_func(Uniforms[i].location, 1, Uniforms[i].value);
181 break;
182 case 3:
183 glUniform3fv_func(Uniforms[i].location, 1, Uniforms[i].value);
184 break;
185 case 4:
186 glUniform4fv_func(Uniforms[i].location, 1, Uniforms[i].value);
187 break;
188 default:
189 abort();
190 }
191 }
192
193 uZoom = glGetUniformLocation_func(program, "Zoom");
194 uXcenter = glGetUniformLocation_func(program, "Xcenter");
195 uYcenter = glGetUniformLocation_func(program, "Ycenter");
196
197 assert(glGetError() == 0);
198
199 glClearColor(0.4f, 0.4f, 0.8f, 0.0f);
200
201 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
202
203 assert(glIsProgram_func(program));
204 assert(glIsShader_func(fragShader));
205 assert(glIsShader_func(vertShader));
206
207 glColor3f(1, 0, 0);
208 }
209
210
211 static void
212 ParseOptions(int argc, char *argv[])
213 {
214 int i;
215 for (i = 1; i < argc; i++) {
216 if (strcmp(argv[i], "-fs") == 0) {
217 FragProgFile = argv[i+1];
218 }
219 else if (strcmp(argv[i], "-vs") == 0) {
220 VertProgFile = argv[i+1];
221 }
222 }
223 }
224
225
226 int
227 main(int argc, char *argv[])
228 {
229 glutInit(&argc, argv);
230 glutInitWindowPosition( 0, 0);
231 glutInitWindowSize(400, 400);
232 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
233 win = glutCreateWindow(argv[0]);
234 glutReshapeFunc(Reshape);
235 glutKeyboardFunc(Key);
236 glutSpecialFunc(SpecialKey);
237 glutDisplayFunc(Redisplay);
238 ParseOptions(argc, argv);
239 Init();
240 glutMainLoop();
241 return 0;
242 }
243