WIP - port to Mali EGL
[mesa-demos/mali.git] / src / glsl / geom-stipple-lines.c
blob8b051a34f6822285bf0c6ce55f04f86c6963c8cd
1 /**
2 * Test using a geometry and fragment shaders to implement stippled lines.
4 * Brian Paul
5 * April 2011
6 */
8 #include <assert.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <math.h>
13 #include <GL/glew.h>
14 #include "glut_wrap.h"
15 #include "shaderutil.h"
17 static GLint WinWidth = 500, WinHeight = 500;
18 static GLint Win = 0;
19 static GLuint VertShader, GeomShader, FragShader, Program;
20 static GLboolean Anim = GL_TRUE;
21 static GLboolean UseGeomShader = GL_TRUE;
22 static GLfloat Xrot = 0, Yrot = 0;
23 static int uViewportSize = -1, uStippleFactor = -1, uStipplePattern = -1;
24 static const int NumPoints = 50;
25 static float Points[100][3], Colors[100][3];
27 static const GLushort StipplePattern = 0x10ff;
28 static GLuint StippleFactor = 2;
31 static void
32 CheckError(int line)
34 GLenum err = glGetError();
35 if (err) {
36 printf("GL Error %s (0x%x) at line %d\n",
37 gluErrorString(err), (int) err, line);
42 /**
43 * Set stipple factor and pattern for geometry shader.
45 * We convert the 16-bit stipple pattern into an array of 16 float values
46 * then pass the array as a uniform variable.
48 * Note: With GLSL 1.30 or later the stipple pattern could be implemented
49 * as an ordinary integer since GLSL 1.30 has true integer types and bit
50 * shifts and bit masks.
53 static void
54 SetStippleUniform(GLint factor, GLushort pattern)
56 GLfloat p[16];
57 int i;
58 for (i = 0; i < 16; i++) {
59 p[i] = (pattern & (1 << i)) ? 1.0f : 0.0f;
61 glUniform1fv(uStipplePattern, 16, p);
62 glUniform1f(uStippleFactor, factor);
66 static void
67 Redisplay(void)
69 int i;
71 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
73 glPushMatrix();
74 glRotatef(Xrot, 1, 0, 0);
75 glRotatef(Yrot, 0, 0, 1);
77 if (UseGeomShader) {
78 glUseProgram(Program);
79 glDisable(GL_LINE_STIPPLE);
81 else {
82 glUseProgram(0);
83 glEnable(GL_LINE_STIPPLE);
86 glBegin(GL_LINES);
87 for (i = 0; i < NumPoints; i++) {
88 glColor3fv(Colors[i]);
89 glVertex3fv(Points[i]);
91 glEnd();
93 glPopMatrix();
95 glutSwapBuffers();
99 static void
100 Idle(void)
102 int curTime = glutGet(GLUT_ELAPSED_TIME);
103 Xrot = curTime * 0.02;
104 Yrot = curTime * 0.05;
105 glutPostRedisplay();
109 static void
110 Reshape(int width, int height)
112 float ar = (float) width / height;
113 glViewport(0, 0, width, height);
114 glMatrixMode(GL_PROJECTION);
115 glLoadIdentity();
116 #if 1
117 glFrustum(-ar, ar, -1, 1, 3, 25);
118 #else
119 glOrtho(-3.0*ar, 3.0*ar, -3.0, 3.0, 3, 25);
120 #endif
121 glMatrixMode(GL_MODELVIEW);
122 glLoadIdentity();
123 glTranslatef(0, 0, -10);
126 GLfloat viewport[4];
127 glGetFloatv(GL_VIEWPORT, viewport);
128 glUniform2f(uViewportSize, viewport[2], viewport[3]);
133 static void
134 CleanUp(void)
136 glDeleteShader(FragShader);
137 glDeleteShader(VertShader);
138 glDeleteShader(GeomShader);
139 glDeleteProgram(Program);
140 glutDestroyWindow(Win);
144 static void
145 Key(unsigned char key, int x, int y)
147 (void) x;
148 (void) y;
150 switch(key) {
151 case ' ':
152 case 'a':
153 Anim = !Anim;
154 if (Anim) {
155 glutIdleFunc(Idle);
157 else
158 glutIdleFunc(NULL);
159 break;
160 case 'g':
161 UseGeomShader = !UseGeomShader;
162 printf("Use geometry shader? %d\n", UseGeomShader);
163 break;
164 case 'x':
165 Xrot ++;
166 break;
167 case 27:
168 CleanUp();
169 exit(0);
170 break;
172 glutPostRedisplay();
176 static void
177 MakePoints(void)
179 int i;
180 for (i = 0; i < NumPoints; i++) {
181 Colors[i][0] = (rand() % 1000) / 1000.0;
182 Colors[i][1] = (rand() % 1000) / 1000.0;
183 Colors[i][2] = (rand() % 1000) / 1000.0;
184 Points[i][0] = ((rand() % 2000) - 1000.0) / 500.0;
185 Points[i][1] = ((rand() % 2000) - 1000.0) / 500.0;
186 Points[i][2] = ((rand() % 2000) - 1000.0) / 500.0;
191 static void
192 Init(void)
194 static const char *fragShaderText =
195 "uniform float StipplePattern[16]; \n"
196 "varying float stippleCoord; \n"
197 "void main() \n"
198 "{ \n"
199 " // check the stipple pattern and discard if value is zero \n"
200 " // TODO: we should really undo the perspective interpolation here \n"
201 " // so that it's linear. \n"
202 " float stip = StipplePattern[int(fract(stippleCoord) * 16.0)]; \n"
203 " if (stip == 0.0) \n"
204 " discard; \n"
205 " gl_FragColor = gl_Color; \n"
206 "} \n";
207 static const char *vertShaderText =
208 "void main() \n"
209 "{ \n"
210 " gl_FrontColor = gl_Color; \n"
211 " gl_Position = ftransform(); \n"
212 "} \n";
213 static const char *geomShaderText =
214 "#version 120 \n"
215 "#extension GL_ARB_geometry_shader4: enable \n"
216 "uniform vec2 ViewportSize; \n"
217 "uniform float StippleFactor; \n"
218 "varying float stippleCoord; \n"
219 "void main() \n"
220 "{ \n"
221 " vec4 pos0 = gl_PositionIn[0]; \n"
222 " vec4 pos1 = gl_PositionIn[1]; \n"
223 " // Convert eye coords to window coords \n"
224 " // Note: we're off by a factor of two here, make up for that below \n"
225 " vec2 p0 = pos0.xy / pos0.w * ViewportSize; \n"
226 " vec2 p1 = pos1.xy / pos1.w * ViewportSize; \n"
227 " float len = length(p0.xy - p1.xy); \n"
228 " // Emit first vertex \n"
229 " gl_FrontColor = gl_FrontColorIn[0]; \n"
230 " gl_Position = pos0; \n"
231 " stippleCoord = 0.0; \n"
232 " EmitVertex(); \n"
233 " // Emit second vertex \n"
234 " gl_FrontColor = gl_FrontColorIn[1]; \n"
235 " gl_Position = pos1; \n"
236 " stippleCoord = len / StippleFactor / 32.0; // Note: not 16, see above \n"
237 " EmitVertex(); \n"
238 "} \n";
240 if (!ShadersSupported())
241 exit(1);
243 if (!glutExtensionSupported("GL_ARB_geometry_shader4")) {
244 fprintf(stderr, "Sorry, GL_ARB_geometry_shader4 is not supported.\n");
245 exit(1);
248 VertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
249 FragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
250 GeomShader = CompileShaderText(GL_GEOMETRY_SHADER_ARB, geomShaderText);
251 assert(GeomShader);
253 Program = LinkShaders3(VertShader, GeomShader, FragShader);
254 assert(Program);
255 CheckError(__LINE__);
258 * The geometry shader accepts lines and produces lines.
260 glProgramParameteriARB(Program, GL_GEOMETRY_INPUT_TYPE_ARB,
261 GL_LINES);
262 glProgramParameteriARB(Program, GL_GEOMETRY_OUTPUT_TYPE_ARB,
263 GL_LINE_STRIP);
264 glProgramParameteriARB(Program, GL_GEOMETRY_VERTICES_OUT_ARB, 4);
265 CheckError(__LINE__);
267 glLinkProgramARB(Program);
269 /* check link */
271 GLint stat;
272 GetProgramiv(Program, GL_LINK_STATUS, &stat);
273 if (!stat) {
274 GLchar log[1000];
275 GLsizei len;
276 GetProgramInfoLog(Program, 1000, &len, log);
277 fprintf(stderr, "Shader link error:\n%s\n", log);
281 glUseProgram(Program);
283 uViewportSize = glGetUniformLocation(Program, "ViewportSize");
284 uStippleFactor = glGetUniformLocation(Program, "StippleFactor");
285 uStipplePattern = glGetUniformLocation(Program, "StipplePattern");
287 glUniform1f(uStippleFactor, StippleFactor);
289 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
291 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
293 assert(glIsProgram(Program));
294 assert(glIsShader(FragShader));
295 assert(glIsShader(VertShader));
296 assert(glIsShader(GeomShader));
299 glLineStipple(StippleFactor, StipplePattern);
300 SetStippleUniform(StippleFactor, StipplePattern);
302 MakePoints();
307 main(int argc, char *argv[])
309 glutInit(&argc, argv);
310 glutInitWindowSize(WinWidth, WinHeight);
311 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
312 Win = glutCreateWindow(argv[0]);
313 glewInit();
314 glutReshapeFunc(Reshape);
315 glutKeyboardFunc(Key);
316 glutDisplayFunc(Redisplay);
317 if (Anim)
318 glutIdleFunc(Idle);
320 Init();
321 glutMainLoop();
322 return 0;