texaaline.c revision 32001f49
1/** 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/glew.h> 15#include "glut_wrap.h" 16 17#ifndef M_PI 18#define M_PI 3.1415926535 19#endif 20 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{ 109 float cx = 0.5 * WinWidth, cy = 0.5 * WinHeight; 110 float len = 0.5 * WinWidth - 20.0; 111 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]; 122 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); 126 QuadLine(v0, v1, Width); 127 } 128 129 { 130 float v0[2], v1[2], x; 131 for (x = 0; x < 1.0; x += 0.2) { 132 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; 136 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{ 150 WinWidth = width; 151 WinHeight = height; 152 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); 313 /* glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); */ 314 /* glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5); */ 315 316 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 317#undef SZ 318} 319 320 321static void 322Init(void) 323{ 324 (void) MakeTexture; 325 (void) ramp4; 326 (void) ramp2; 327 328 if (!GLEW_VERSION_2_0) { 329 printf("This program requires OpenGL 2.x\n"); 330 exit(1); 331 } 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 glutInitWindowSize(WinWidth, WinHeight); 359 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 360 win = glutCreateWindow(argv[0]); 361 glewInit(); 362 glutReshapeFunc(Reshape); 363 glutKeyboardFunc(Key); 364 glutDisplayFunc(Redisplay); 365 ParseOptions(argc, argv); 366 Init(); 367 glutMainLoop(); 368 return 0; 369} 370