blob: 4ad5a761c67f04f4f77bfd995c5a4ba8fd36d2ef [file] [log] [blame]
Brian Paulc0565e82009-04-18 14:18:59 -06001/**
2 * AA lines with texture mapped quads
3 *
4 * Brian Paul
5 * 9 Feb 2008
6 */
7
8
9#include <assert.h>
10#include <string.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <math.h>
Keith Whitwellb799af92009-06-29 14:13:58 +010014#include <GL/glew.h>
Brian Paulc0565e82009-04-18 14:18:59 -060015#include <GL/glut.h>
Brian Paulc0565e82009-04-18 14:18:59 -060016
Jon TURNEYa15d9ca2009-07-24 20:33:25 +010017#ifndef M_PI
18#define M_PI 3.1415926535
19#endif
Brian Paulc0565e82009-04-18 14:18:59 -060020
21static GLint WinWidth = 300, WinHeight = 300;
22static GLint win = 0;
23static GLfloat Width = 8.;
24
25/*
26 * Quad strip for line from v0 to v1:
27 *
28 1 3 5 7
29 +---+---------------------+---+
30 | |
31 | *v0 v1* |
32 | |
33 +---+---------------------+---+
34 0 2 4 6
35 */
36static void
37QuadLine(const GLfloat *v0, const GLfloat *v1, GLfloat width)
38{
39 GLfloat dx = v1[0] - v0[0];
40 GLfloat dy = v1[1] - v0[1];
41 GLfloat len = sqrt(dx*dx + dy*dy);
42 float dx0, dx1, dx2, dx3, dx4, dx5, dx6, dx7;
43 float dy0, dy1, dy2, dy3, dy4, dy5, dy6, dy7;
44
45 dx /= len;
46 dy /= len;
47
48 width *= 0.5; /* half width */
49 dx = dx * (width + 0.0);
50 dy = dy * (width + 0.0);
51
52 dx0 = -dx+dy; dy0 = -dy-dx;
53 dx1 = -dx-dy; dy1 = -dy+dx;
54
55 dx2 = 0+dy; dy2 = -dx+0;
56 dx3 = 0-dy; dy3 = +dx+0;
57
58 dx4 = 0+dy; dy4 = -dx+0;
59 dx5 = 0-dy; dy5 = +dx+0;
60
61 dx6 = dx+dy; dy6 = dy-dx;
62 dx7 = dx-dy; dy7 = dy+dx;
63
64 /*
65 printf("dx, dy = %g, %g\n", dx, dy);
66 printf(" dx0, dy0: %g, %g\n", dx0, dy0);
67 printf(" dx1, dy1: %g, %g\n", dx1, dy1);
68 printf(" dx2, dy2: %g, %g\n", dx2, dy2);
69 printf(" dx3, dy3: %g, %g\n", dx3, dy3);
70 */
71
72 glBegin(GL_QUAD_STRIP);
73 glTexCoord2f(0, 0);
74 glVertex2f(v0[0] + dx0, v0[1] + dy0);
75 glTexCoord2f(0, 1);
76 glVertex2f(v0[0] + dx1, v0[1] + dy1);
77
78 glTexCoord2f(0.5, 0);
79 glVertex2f(v0[0] + dx2, v0[1] + dy2);
80 glTexCoord2f(0.5, 1);
81 glVertex2f(v0[0] + dx3, v0[1] + dy3);
82
83 glTexCoord2f(0.5, 0);
84 glVertex2f(v1[0] + dx2, v1[1] + dy2);
85 glTexCoord2f(0.5, 1);
86 glVertex2f(v1[0] + dx3, v1[1] + dy3);
87
88 glTexCoord2f(1, 0);
89 glVertex2f(v1[0] + dx6, v1[1] + dy6);
90 glTexCoord2f(1, 1);
91 glVertex2f(v1[0] + dx7, v1[1] + dy7);
92 glEnd();
93}
94
95
96static float Cos(float a)
97{
98 return cos(a * M_PI / 180.);
99}
100
101static float Sin(float a)
102{
103 return sin(a * M_PI / 180.);
104}
105
106static void
107Redisplay(void)
108{
Brian Paul2bcf7872009-08-26 11:56:19 -0600109 float cx = 0.5 * WinWidth, cy = 0.5 * WinHeight;
110 float len = 0.5 * WinWidth - 20.0;
Brian Paulc0565e82009-04-18 14:18:59 -0600111 int i;
112
113 glClear(GL_COLOR_BUFFER_BIT);
114
115 glColor3f(1, 1, 1);
116
117 glEnable(GL_BLEND);
118 glEnable(GL_TEXTURE_2D);
119
120 for (i = 0; i < 360; i+=5) {
121 float v0[2], v1[2];
Brian Paul2bcf7872009-08-26 11:56:19 -0600122 v0[0] = cx + 40 * Cos(i);
123 v0[1] = cy + 40 * Sin(i);
124 v1[0] = cx + len * Cos(i);
125 v1[1] = cy + len * Sin(i);
Brian Paulc0565e82009-04-18 14:18:59 -0600126 QuadLine(v0, v1, Width);
127 }
128
129 {
130 float v0[2], v1[2], x;
131 for (x = 0; x < 1.0; x += 0.2) {
Brian Paul2bcf7872009-08-26 11:56:19 -0600132 v0[0] = cx + x;
133 v0[1] = cy + x * 40 - 20;
134 v1[0] = cx + x + 5.0;
135 v1[1] = cy + x * 40 - 20;
Brian Paulc0565e82009-04-18 14:18:59 -0600136 QuadLine(v0, v1, Width);
137 }
138 }
139
140 glDisable(GL_BLEND);
141 glDisable(GL_TEXTURE_2D);
142
143 glutSwapBuffers();
144}
145
146
147static void
148Reshape(int width, int height)
149{
Brian Paul2bcf7872009-08-26 11:56:19 -0600150 WinWidth = width;
151 WinHeight = height;
Brian Paulc0565e82009-04-18 14:18:59 -0600152 glViewport(0, 0, width, height);
153 glMatrixMode(GL_PROJECTION);
154 glLoadIdentity();
155 glOrtho(0, width, 0, height, -1, 1);
156 glMatrixMode(GL_MODELVIEW);
157 glLoadIdentity();
158}
159
160
161static void
162CleanUp(void)
163{
164 glutDestroyWindow(win);
165}
166
167
168static void
169Key(unsigned char key, int x, int y)
170{
171 (void) x;
172 (void) y;
173
174 switch(key) {
175 case 'w':
176 Width -= 0.5;
177 break;
178 case 'W':
179 Width += 0.5;
180 break;
181 case 27:
182 CleanUp();
183 exit(0);
184 break;
185 }
186#if 0
187 if (Width < 3)
188 Width = 3;
189#endif
190 printf("Width = %g\n", Width);
191 glutPostRedisplay();
192}
193
194
195static float
196ramp4(GLint i, GLint size)
197{
198 float d;
199 if (i < 4 ) {
200 d = i / 4.0;
201 }
202 else if (i >= size - 5) {
203 d = 1.0 - (i - (size - 5)) / 4.0;
204 }
205 else {
206 d = 1.0;
207 }
208 return d;
209}
210
211static float
212ramp2(GLint i, GLint size)
213{
214 float d;
215 if (i < 2 ) {
216 d = i / 2.0;
217 }
218 else if (i >= size - 3) {
219 d = 1.0 - (i - (size - 3)) / 2.0;
220 }
221 else {
222 d = 1.0;
223 }
224 return d;
225}
226
227static float
228ramp1(GLint i, GLint size)
229{
230 float d;
231 if (i == 0 || i == size-1) {
232 d = 0.0;
233 }
234 else {
235 d = 1.0;
236 }
237 return d;
238}
239
240
241/**
242 * Make an alpha texture for antialiasing lines.
243 * Just a linear fall-off ramp for now.
244 * Should have a number of different textures for different line widths.
245 * Could try a bell-like-curve....
246 */
247static void
248MakeTexture(void)
249{
250#define SZ 8
251 GLfloat tex[SZ][SZ]; /* alpha tex */
252 int i, j;
253 for (i = 0; i < SZ; i++) {
254 for (j = 0; j < SZ; j++) {
255#if 0
256 float k = (SZ-1) / 2.0;
257 float dx = fabs(i - k) / k;
258 float dy = fabs(j - k) / k;
259 float d;
260
261 dx = 1.0 - dx;
262 dy = 1.0 - dy;
263 d = dx * dy;
264
265#else
266 float d = ramp1(i, SZ) * ramp1(j, SZ);
267 printf("%d, %d: %g\n", i, j, d);
268#endif
269 tex[i][j] = d;
270 }
271 }
272
273 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, SZ, SZ, 0, GL_ALPHA, GL_FLOAT, tex);
274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
277 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
278 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
279#undef SZ
280}
281
282
283static void
284MakeMipmap(void)
285{
286#define SZ 64
287 GLfloat tex[SZ][SZ]; /* alpha tex */
288 int level;
289
290 glPixelStorei(GL_UNPACK_ROW_LENGTH, SZ);
291 for (level = 0; level < 7; level++) {
292 int sz = 1 << (6 - level);
293 int i, j;
294 for (i = 0; i < sz; i++) {
295 for (j = 0; j < sz; j++) {
296 if (level == 6)
297 tex[i][j] = 1.0;
298 else if (level == 5)
299 tex[i][j] = 0.5;
300 else
301 tex[i][j] = ramp1(i, sz) * ramp1(j, sz);
302 }
303 }
304
305 glTexImage2D(GL_TEXTURE_2D, level, GL_ALPHA,
306 sz, sz, 0, GL_ALPHA, GL_FLOAT, tex);
307 }
308
309 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
310 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Brian Paulb08f4472009-11-17 16:14:09 -0700313 /*
314 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
315 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5);
316 */
Brian Paulc0565e82009-04-18 14:18:59 -0600317
318 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
319#undef SZ
320}
321
322
323static void
324Init(void)
325{
326 const char *version;
327
328 (void) MakeTexture;
329 (void) ramp4;
330 (void) ramp2;
331
332 version = (const char *) glGetString(GL_VERSION);
333 if (version[0] != '2' || version[1] != '.') {
334 printf("This program requires OpenGL 2.x, found %s\n", version);
335 exit(1);
336 }
337
Brian Paulc0565e82009-04-18 14:18:59 -0600338 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
339
340 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
341
342 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
343#if 0
344 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
345#elif 0
346 MakeTexture();
347#else
348 MakeMipmap();
349#endif
350}
351
352
353static void
354ParseOptions(int argc, char *argv[])
355{
356}
357
358
359int
360main(int argc, char *argv[])
361{
362 glutInit(&argc, argv);
Brian Paulc0565e82009-04-18 14:18:59 -0600363 glutInitWindowSize(WinWidth, WinHeight);
364 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
365 win = glutCreateWindow(argv[0]);
Keith Whitwellb799af92009-06-29 14:13:58 +0100366 glewInit();
Brian Paulc0565e82009-04-18 14:18:59 -0600367 glutReshapeFunc(Reshape);
368 glutKeyboardFunc(Key);
369 glutDisplayFunc(Redisplay);
370 ParseOptions(argc, argv);
371 Init();
372 glutMainLoop();
373 return 0;
374}