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