1/**
2 * Test/demo of Ian McEwan's simplex noise function.
3 * See https://github.com/ashima/webgl-noise
4 *
5 * Brian Paul
6 * 17 March 2011
7 */
8
9#include <assert.h>
10#include <string.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <math.h>
14#include <GL/glew.h>
15#include "glut_wrap.h"
16#include "shaderutil.h"
17
18
19static const char *VertShaderText =
20   "void main() {\n"
21   "   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
22   "   gl_TexCoord[0] = gl_MultiTexCoord0;\n"
23   "}\n";
24
25static const char *FragShaderMainText =
26   "uniform float Slice;\n"
27   "void main()\n"
28   "{\n"
29   "   vec3 c = vec3(3.0 * gl_TexCoord[0].xy, Slice);\n"
30   "   float r = simplexNoise3(c); \n"
31   "   gl_FragColor = vec4(r, r, r, 1.0);;\n"
32   "}\n";
33
34
35static struct uniform_info Uniforms[] = {
36   { "pParam",   1, GL_FLOAT_VEC4, { 17*17, 3, 2, 3 }, -1 },
37   { "Slice",    1, GL_FLOAT, { 0.5, 0, 0, 0}, -1 },
38   END_OF_UNIFORMS
39};
40
41/* program/shader objects */
42static GLuint fragShader;
43static GLuint vertShader;
44static GLuint program;
45
46static GLint win = 0;
47static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f;
48static GLfloat Slice = 0.0;
49static GLboolean Anim = GL_TRUE;
50static GLint ParamUniform = -1, SliceUniform = -1;
51
52
53static void
54Idle(void)
55{
56   Slice = glutGet(GLUT_ELAPSED_TIME) * 0.001;
57   glutPostRedisplay();
58}
59
60
61static void
62Redisplay(void)
63{
64   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
65
66   glUniform1f(SliceUniform, Slice);
67
68   glPushMatrix();
69   glRotatef(xRot, 1.0f, 0.0f, 0.0f);
70   glRotatef(yRot, 0.0f, 1.0f, 0.0f);
71   glRotatef(zRot, 0.0f, 0.0f, 1.0f);
72
73   glBegin(GL_POLYGON);
74   glTexCoord2f(0, 0);   glVertex2f(-2, -2);
75   glTexCoord2f(1, 0);   glVertex2f( 2, -2);
76   glTexCoord2f(1, 1);   glVertex2f( 2,  2);
77   glTexCoord2f(0, 1);   glVertex2f(-2,  2);
78   glEnd();
79
80   glPopMatrix();
81
82   glutSwapBuffers();
83}
84
85
86static void
87Reshape(int width, int height)
88{
89   glViewport(0, 0, width, height);
90   glMatrixMode(GL_PROJECTION);
91   glLoadIdentity();
92   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
93   glMatrixMode(GL_MODELVIEW);
94   glLoadIdentity();
95   glTranslatef(0.0f, 0.0f, -15.0f);
96}
97
98
99static void
100CleanUp(void)
101{
102   glDeleteShader(fragShader);
103   glDeleteShader(vertShader);
104   glDeleteProgram(program);
105   glutDestroyWindow(win);
106}
107
108
109static void
110Key(unsigned char key, int x, int y)
111{
112   const GLfloat step = 1.0;//0.01;
113  (void) x;
114  (void) y;
115
116   switch(key) {
117   case 'a':
118      Anim = !Anim;
119      glutIdleFunc(Anim ? Idle : NULL);
120      break;
121   case 's':
122      Slice -= step;
123      break;
124   case 'S':
125      Slice += step;
126      break;
127   case 'z':
128      zRot -= 1.0;
129      break;
130   case 'Z':
131      zRot += 1.0;
132      break;
133   case 27:
134      CleanUp();
135      exit(0);
136      break;
137   }
138   glutPostRedisplay();
139}
140
141
142static void
143SpecialKey(int key, int x, int y)
144{
145   const GLfloat step = 3.0f;
146
147  (void) x;
148  (void) y;
149
150   switch(key) {
151   case GLUT_KEY_UP:
152      xRot -= step;
153      break;
154   case GLUT_KEY_DOWN:
155      xRot += step;
156      break;
157   case GLUT_KEY_LEFT:
158      yRot -= step;
159      break;
160   case GLUT_KEY_RIGHT:
161      yRot += step;
162      break;
163   }
164   glutPostRedisplay();
165}
166
167
168
169static void
170Init(void)
171{
172   const char *filename = "simplex-noise.glsl";
173   char noiseText[10000];
174   FILE *f;
175   int len;
176
177   f = fopen(filename, "r");
178   if (!f) {
179      fprintf(stderr, "Unable to open %s\n", filename);
180      exit(1);
181   }
182
183   len = fread(noiseText, 1, sizeof(noiseText), f);
184   fclose(f);
185
186   /* append main() code onto buffer */
187   strcpy(noiseText + len, FragShaderMainText);
188
189   if (!ShadersSupported())
190      exit(1);
191
192   vertShader = CompileShaderText(GL_VERTEX_SHADER, VertShaderText);
193   fragShader = CompileShaderText(GL_FRAGMENT_SHADER, noiseText);
194   program = LinkShaders(vertShader, fragShader);
195
196   glUseProgram(program);
197
198   ParamUniform = glGetUniformLocation(program, "pParam");
199   SliceUniform = glGetUniformLocation(program, "Slice");
200
201   SetUniformValues(program, Uniforms);
202   PrintUniforms(Uniforms);
203
204   assert(glGetError() == 0);
205
206   glClearColor(0.4f, 0.4f, 0.8f, 0.0f);
207
208   printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
209
210   assert(glIsProgram(program));
211   assert(glIsShader(fragShader));
212   assert(glIsShader(vertShader));
213
214   glColor3f(1, 0, 0);
215}
216
217
218int
219main(int argc, char *argv[])
220{
221   glutInit(&argc, argv);
222   glutInitWindowSize(400, 400);
223   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
224   win = glutCreateWindow(argv[0]);
225   glewInit();
226   glutReshapeFunc(Reshape);
227   glutKeyboardFunc(Key);
228   glutSpecialFunc(SpecialKey);
229   glutDisplayFunc(Redisplay);
230   glutIdleFunc(Anim ? Idle : NULL);
231   Init();
232   glutMainLoop();
233   return 0;
234}
235
236