Use glad instead of GLEW.
[mesa-demos.git] / src / glsl / geom-wide-lines.c
blobebcbb32f005178d62dfb322c4d48420debe9b901
1 /**
2 * Test using a geometry shader to implement wide lines.
4 * Brian Paul
5 * March 2011
6 */
8 #include <assert.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <math.h>
13 #include <glad/glad.h>
14 #include "glut_wrap.h"
15 #include "shaderutil.h"
18 static GLint WinWidth = 500, WinHeight = 500;
19 static GLint Win = 0;
20 static GLuint VertShader, GeomShader, FragShader, Program;
21 static GLboolean Anim = GL_TRUE;
22 static GLboolean UseGeomShader = GL_TRUE;
23 static GLfloat LineWidth = 10.0;
24 static GLfloat MaxLineWidth;
25 static GLfloat Xrot = 0, Yrot = 0;
26 static int uLineWidth = -1, uInverseViewportSize = -1;
28 static int NumPoints = 50;
30 static void
31 CheckError(int line)
33 GLenum err = glGetError();
34 if (err) {
35 printf("GL Error %s (0x%x) at line %d\n",
36 gluErrorString(err), (int) err, line);
41 static void
42 Redisplay(void)
44 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
46 glPushMatrix();
47 glRotatef(Xrot, 1, 0, 0);
48 glRotatef(Yrot, 0, 0, 1);
50 if (UseGeomShader) {
51 glUseProgram(Program);
52 glUniform1f(uLineWidth, LineWidth);
54 else {
55 glUseProgram(0);
56 glLineWidth(LineWidth);
59 glDrawArrays(GL_LINES, 0, NumPoints / 2);
61 glPopMatrix();
63 glutSwapBuffers();
67 static void
68 Idle(void)
70 int curTime = glutGet(GLUT_ELAPSED_TIME);
71 Xrot = curTime * 0.02;
72 Yrot = curTime * 0.05;
73 glutPostRedisplay();
77 static void
78 Reshape(int width, int height)
80 float ar = (float) width / height;
81 glViewport(0, 0, width, height);
82 glMatrixMode(GL_PROJECTION);
83 glLoadIdentity();
84 glFrustum(-ar, ar, -1, 1, 3, 25);
85 glMatrixMode(GL_MODELVIEW);
86 glLoadIdentity();
87 glTranslatef(0, 0, -10);
90 GLfloat viewport[4];
91 glGetFloatv(GL_VIEWPORT, viewport);
92 glUniform2f(uInverseViewportSize, 1.0F / viewport[2], 1.0F / viewport[3]);
97 static void
98 CleanUp(void)
100 glDeleteShader(FragShader);
101 glDeleteShader(VertShader);
102 glDeleteShader(GeomShader);
103 glDeleteProgram(Program);
104 glutDestroyWindow(Win);
108 static void
109 Key(unsigned char key, int x, int y)
111 (void) x;
112 (void) y;
114 switch(key) {
115 case ' ':
116 case 'a':
117 Anim = !Anim;
118 if (Anim) {
119 glutIdleFunc(Idle);
121 else
122 glutIdleFunc(NULL);
123 break;
124 case 'g':
125 UseGeomShader = !UseGeomShader;
126 printf("Use geometry shader? %d\n", UseGeomShader);
127 break;
128 case 'w':
129 LineWidth -= 0.5;
130 if (LineWidth < 1.0)
131 LineWidth = 1.0;
132 printf("Line width: %f\n", LineWidth);
133 break;
134 case 'W':
135 LineWidth += 0.5;
136 if (LineWidth > MaxLineWidth)
137 LineWidth = MaxLineWidth;
138 printf("Line width: %f\n", LineWidth);
139 break;
141 case 27:
142 CleanUp();
143 exit(0);
144 break;
146 glutPostRedisplay();
150 static void
151 MakePointsVBO(void)
153 struct vert {
154 GLfloat pos[3];
155 GLfloat color[3];
157 struct vert *v;
158 GLuint vbo;
159 int i;
161 glGenBuffers(1, &vbo);
162 glBindBuffer(GL_ARRAY_BUFFER, vbo);
163 glBufferData(GL_ARRAY_BUFFER, NumPoints * sizeof(struct vert),
164 NULL, GL_STATIC_DRAW);
166 v = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
167 for (i = 0; i < NumPoints; i++) {
168 v[i].color[0] = (rand() % 1000) / 1000.0;
169 v[i].color[1] = (rand() % 1000) / 1000.0;
170 v[i].color[2] = (rand() % 1000) / 1000.0;
171 v[i].pos[0] = ((rand() % 2000) - 1000.0) / 500.0;
172 v[i].pos[1] = ((rand() % 2000) - 1000.0) / 500.0;
173 v[i].pos[2] = ((rand() % 2000) - 1000.0) / 500.0;
175 glUnmapBuffer(GL_ARRAY_BUFFER);
177 glVertexPointer(3, GL_FLOAT, sizeof(struct vert), (void *) 0);
178 glEnable(GL_VERTEX_ARRAY);
179 glColorPointer(3, GL_FLOAT, sizeof(struct vert), (void *) sizeof(float[3]));
180 glEnable(GL_COLOR_ARRAY);
184 static void
185 Init(void)
187 static const char *fragShaderText =
188 "void main() \n"
189 "{ \n"
190 " gl_FragColor = gl_Color; \n"
191 "} \n";
192 static const char *vertShaderText =
193 "void main() \n"
194 "{ \n"
195 " gl_FrontColor = gl_Color; \n"
196 " gl_Position = ftransform(); \n"
197 "} \n";
198 static const char *geomShaderText =
199 "#version 120 \n"
200 "#extension GL_ARB_geometry_shader4: enable \n"
201 "uniform vec2 InverseViewportSize; \n"
202 "uniform float LineWidth; \n"
203 "void main() \n"
204 "{ \n"
205 " vec4 pos0 = gl_PositionIn[0]; \n"
206 " vec4 pos1 = gl_PositionIn[1]; \n"
207 " vec4 dir = abs(pos1 - pos0); \n"
208 " vec2 d0 = vec2(LineWidth * pos0.w) * InverseViewportSize; \n"
209 " vec2 d1 = vec2(LineWidth * pos1.w) * InverseViewportSize; \n"
210 " // this conditional could be avoided \n"
211 " if (dir.x > dir.y) { \n"
212 " // X-major line \n"
213 " d0.x = 0.0; \n"
214 " d1.x = 0.0; \n"
215 " } \n"
216 " else { \n"
217 " // Y-major line \n"
218 " d0.y = 0.0; \n"
219 " d1.y = 0.0; \n"
220 " } \n"
221 " gl_FrontColor = gl_FrontColorIn[0]; \n"
222 " gl_TexCoord[0] = vec4(0, 0, 0, 1); \n"
223 " gl_Position = pos0 + vec4( d0.x, -d0.y, 0, 0); \n"
224 " EmitVertex(); \n"
225 " gl_FrontColor = gl_FrontColorIn[1]; \n"
226 " gl_TexCoord[0] = vec4(1, 0, 0, 1); \n"
227 " gl_Position = pos1 + vec4( d1.x, -d1.y, 0, 0); \n"
228 " EmitVertex(); \n"
229 " gl_FrontColor = gl_FrontColorIn[0]; \n"
230 " gl_TexCoord[0] = vec4(0, 1, 0, 1); \n"
231 " gl_Position = pos0 + vec4(-d0.x, d0.y, 0, 0); \n"
232 " EmitVertex(); \n"
233 " gl_FrontColor = gl_FrontColorIn[1]; \n"
234 " gl_TexCoord[0] = vec4(1, 1, 0, 1); \n"
235 " gl_Position = pos1 + vec4(-d1.x, d1.y, 0, 0); \n"
236 " EmitVertex(); \n"
237 "} \n";
239 if (!ShadersSupported())
240 exit(1);
242 if (!glutExtensionSupported("GL_ARB_geometry_shader4")) {
243 fprintf(stderr, "Sorry, GL_ARB_geometry_shader4 is not supported.\n");
244 exit(1);
247 VertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
248 FragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
249 GeomShader = CompileShaderText(GL_GEOMETRY_SHADER_ARB, geomShaderText);
250 assert(GeomShader);
252 Program = LinkShaders3(VertShader, GeomShader, FragShader);
253 assert(Program);
254 CheckError(__LINE__);
257 * The geometry shader will convert incoming lines to quads (4-vertex
258 * triangle strips).
260 glProgramParameteriARB(Program, GL_GEOMETRY_INPUT_TYPE_ARB,
261 GL_LINES);
262 glProgramParameteriARB(Program, GL_GEOMETRY_OUTPUT_TYPE_ARB,
263 GL_TRIANGLE_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 CheckError(__LINE__);
283 glUseProgram(Program);
284 CheckError(__LINE__);
286 uInverseViewportSize = glGetUniformLocation(Program, "InverseViewportSize");
287 uLineWidth = glGetUniformLocation(Program, "LineWidth");
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));
298 glEnable(GL_DEPTH_TEST);
301 GLfloat r[2];
302 glGetFloatv(GL_LINE_WIDTH_RANGE, r);
303 MaxLineWidth = r[1];
306 MakePointsVBO();
311 main(int argc, char *argv[])
313 glutInit(&argc, argv);
315 if (argc > 1) {
316 int n = atoi(argv[1]);
317 if (n > 0) {
318 NumPoints = n;
320 else {
321 printf("Invalid number of points\n");
322 return 1;
326 glutInitWindowSize(WinWidth, WinHeight);
327 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
328 Win = glutCreateWindow(argv[0]);
329 gladLoadGL();
330 glutReshapeFunc(Reshape);
331 glutKeyboardFunc(Key);
332 glutDisplayFunc(Redisplay);
333 if (Anim)
334 glutIdleFunc(Idle);
336 Init();
337 glutMainLoop();
338 return 0;