1/** 2 * Test variable array indexing in a vertex shader. 3 * Brian Paul 4 * 17 April 2009 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/glew.h> 13#include "glut_wrap.h" 14#include "shaderutil.h" 15 16 17/** 18 * The vertex position.z is used as a (variable) index into an 19 * array which returns a new Z value. 20 */ 21static const char *VertShaderText = 22 "uniform sampler2D tex1; \n" 23 "uniform float HeightArray[20]; \n" 24 "void main() \n" 25 "{ \n" 26 " vec4 pos = gl_Vertex; \n" 27 " int i = int(pos.z * 9.5); \n" 28 " pos.z = HeightArray[i]; \n" 29 " gl_Position = gl_ModelViewProjectionMatrix * pos; \n" 30 " gl_FrontColor = pos; \n" 31 "} \n"; 32 33static const char *FragShaderText = 34 "void main() \n" 35 "{ \n" 36 " gl_FragColor = gl_Color; \n" 37 "} \n"; 38 39 40static GLuint fragShader; 41static GLuint vertShader; 42static GLuint program; 43 44static GLint win = 0; 45static GLboolean Anim = GL_TRUE; 46static GLboolean WireFrame = GL_TRUE; 47static GLfloat xRot = -70.0f, yRot = 0.0f, zRot = 0.0f; 48 49 50static void 51Idle(void) 52{ 53 zRot = 90 + glutGet(GLUT_ELAPSED_TIME) * 0.05; 54 glutPostRedisplay(); 55} 56 57 58/** z=f(x,y) */ 59static float 60fz(float x, float y) 61{ 62 return fabs(cos(1.5*x) + cos(1.5*y)); 63} 64 65 66static void 67DrawMesh(void) 68{ 69 GLfloat xmin = -2.0, xmax = 2.0; 70 GLfloat ymin = -2.0, ymax = 2.0; 71 GLuint xdivs = 20, ydivs = 20; 72 GLfloat dx = (xmax - xmin) / xdivs; 73 GLfloat dy = (ymax - ymin) / ydivs; 74 GLfloat ds = 1.0 / xdivs, dt = 1.0 / ydivs; 75 GLfloat x, y, s, t; 76 GLuint i, j; 77 78 y = ymin; 79 t = 0.0; 80 for (i = 0; i < ydivs; i++) { 81 x = xmin; 82 s = 0.0; 83 glBegin(GL_QUAD_STRIP); 84 for (j = 0; j < xdivs; j++) { 85 float z0 = fz(x, y), z1 = fz(x, y + dy); 86 87 glTexCoord2f(s, t); 88 glVertex3f(x, y, z0); 89 90 glTexCoord2f(s, t + dt); 91 glVertex3f(x, y + dy, z1); 92 x += dx; 93 s += ds; 94 } 95 glEnd(); 96 y += dy; 97 t += dt; 98 } 99} 100 101 102static void 103Redisplay(void) 104{ 105 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 106 107 if (WireFrame) 108 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 109 else 110 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 111 112 glPushMatrix(); 113 glRotatef(xRot, 1.0f, 0.0f, 0.0f); 114 glRotatef(yRot, 0.0f, 1.0f, 0.0f); 115 glRotatef(zRot, 0.0f, 0.0f, 1.0f); 116 117 glPushMatrix(); 118 DrawMesh(); 119 glPopMatrix(); 120 121 glPopMatrix(); 122 123 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 124 125 glutSwapBuffers(); 126} 127 128 129static void 130Reshape(int width, int height) 131{ 132 glViewport(0, 0, width, height); 133 glMatrixMode(GL_PROJECTION); 134 glLoadIdentity(); 135 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); 136 glMatrixMode(GL_MODELVIEW); 137 glLoadIdentity(); 138 glTranslatef(0.0f, 0.0f, -15.0f); 139} 140 141 142static void 143CleanUp(void) 144{ 145 glDeleteShader(fragShader); 146 glDeleteShader(vertShader); 147 glDeleteProgram(program); 148 glutDestroyWindow(win); 149} 150 151 152static void 153Key(unsigned char key, int x, int y) 154{ 155 const GLfloat step = 2.0; 156 (void) x; 157 (void) y; 158 159 switch(key) { 160 case 'a': 161 Anim = !Anim; 162 if (Anim) 163 glutIdleFunc(Idle); 164 else 165 glutIdleFunc(NULL); 166 break; 167 case 'w': 168 WireFrame = !WireFrame; 169 break; 170 case 'z': 171 zRot += step; 172 break; 173 case 'Z': 174 zRot -= step; 175 break; 176 case 27: 177 CleanUp(); 178 exit(0); 179 break; 180 } 181 glutPostRedisplay(); 182} 183 184 185static void 186SpecialKey(int key, int x, int y) 187{ 188 const GLfloat step = 2.0; 189 190 (void) x; 191 (void) y; 192 193 switch(key) { 194 case GLUT_KEY_UP: 195 xRot += step; 196 break; 197 case GLUT_KEY_DOWN: 198 xRot -= step; 199 break; 200 case GLUT_KEY_LEFT: 201 yRot -= step; 202 break; 203 case GLUT_KEY_RIGHT: 204 yRot += step; 205 break; 206 } 207 glutPostRedisplay(); 208} 209 210 211static void 212Init(void) 213{ 214 GLfloat HeightArray[20]; 215 GLint u, i; 216 217 if (!ShadersSupported()) 218 exit(1); 219 220 vertShader = CompileShaderText(GL_VERTEX_SHADER, VertShaderText); 221 fragShader = CompileShaderText(GL_FRAGMENT_SHADER, FragShaderText); 222 program = LinkShaders(vertShader, fragShader); 223 224 glUseProgram(program); 225 226 /* Setup the HeightArray[] uniform */ 227 for (i = 0; i < 20; i++) 228 HeightArray[i] = i / 20.0; 229 u = glGetUniformLocation(program, "HeightArray"); 230 glUniform1fv(u, 20, HeightArray); 231 232 assert(glGetError() == 0); 233 234 glClearColor(0.4f, 0.4f, 0.8f, 0.0f); 235 glEnable(GL_DEPTH_TEST); 236 glColor3f(1, 1, 1); 237} 238 239 240int 241main(int argc, char *argv[]) 242{ 243 glutInit(&argc, argv); 244 glutInitWindowSize(500, 500); 245 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 246 win = glutCreateWindow(argv[0]); 247 glewInit(); 248 glutReshapeFunc(Reshape); 249 glutKeyboardFunc(Key); 250 glutSpecialFunc(SpecialKey); 251 glutDisplayFunc(Redisplay); 252 Init(); 253 if (Anim) 254 glutIdleFunc(Idle); 255 glutMainLoop(); 256 return 0; 257} 258 259