// Anti-aliased lines with gradient fins and gamma-correction half-way // -- Jetro Lauha, May 2011 - http://jet.ro import processing.opengl.*; void setup() { size(220, 130, OPENGL); hint(DISABLE_OPENGL_2X_SMOOTH); frameRate(15); } void aaLine(float x1, float y1, float x2, float y2, float thickness, color c) { final color cb = c & 0xffffff; //final color ch = lerpColor(cb, c, 0.707107); //0.5^0.5 final color ch = lerpColor(cb, c, 0.72974); //0.5^(1/2.2) noStroke(); fill(0xffffffff); final float dx = x2 - x1, dy = y2 - y1; final float len = sqrt(dx * dx + dy * dy); if (len == 0) return; float rx = 0.5 * thickness * -dy / len; float ry = 0.5 * thickness * dx / len; beginShape(TRIANGLES); // R1h fill(c); vertex(x1, y1); vertex(x2, y2); fill(ch); vertex(x1 + rx, y1 + ry); // R2h fill(c); vertex(x2, y2); fill(ch); vertex(x2 + rx, y2 + ry); vertex(x1 + rx, y1 + ry); // L1h fill(c); vertex(x1, y1); fill(ch); vertex(x1 - rx, y1 - ry); fill(c); vertex(x2, y2); // L2h vertex(x2, y2); fill(ch); vertex(x1 - rx, y1 - ry); vertex(x2 - rx, y2 - ry); // R1b fill(ch); vertex(x1 + rx, y1 + ry); vertex(x2 + rx, y2 + ry); fill(cb); vertex(x1 + rx + rx, y1 + ry + ry); // R2b fill(ch); vertex(x2 + rx, y2 + ry); fill(cb); vertex(x2 + rx + rx, y2 + ry + ry); vertex(x1 + rx + rx, y1 + ry + ry); // L1b fill(ch); vertex(x1 - rx, y1 - ry); fill(cb); vertex(x1 - rx - rx, y1 - ry - ry); fill(ch); vertex(x2 - rx, y2 - ry); // L2b vertex(x2 - rx, y2 - ry); fill(cb); vertex(x1 - rx - rx, y1 - ry - ry); vertex(x2 - rx - rx, y2 - ry - ry); endShape(); } void testAALines(float x, float y, float thickness, color c) { pushMatrix(); translate(x, y); aaLine(10, 100, 10, 10, thickness, c); aaLine(20, 100, 30, 10, thickness, c); aaLine(30, 100, 50, 10, thickness, c); aaLine(40, 100, 70, 10, thickness, c); aaLine(50, 100, 90, 10, thickness, c); aaLine(60, 100, 110, 10, thickness, c); aaLine(70, 100, 130, 10, thickness, c); aaLine(80, 100, 140, 20, thickness, c); aaLine(90, 100, 150, 30, thickness, c); aaLine(100, 100, 160, 40, thickness, c); aaLine(110, 100, 170, 50, thickness, c); aaLine(120, 100, 180, 60, thickness, c); aaLine(130, 100, 190, 70, thickness, c); aaLine(140, 100, 200, 80, thickness, c); aaLine(140, 110, 200, 100, thickness, c); aaLine(140, 120, 200, 120, thickness, c); popMatrix(); } void testLines(float x, float y, float thickness, color c) { smooth(); noFill(); stroke(c); strokeWeight(thickness); pushMatrix(); translate(x, y); line(10, 100, 10, 10); line(20, 100, 30, 10); line(30, 100, 50, 10); line(40, 100, 70, 10); line(50, 100, 90, 10); line(60, 100, 110, 10); line(70, 100, 130, 10); line(80, 100, 140, 20); line(90, 100, 150, 30); line(100, 100, 160, 40); line(110, 100, 170, 50); line(120, 100, 180, 60); line(130, 100, 190, 70); line(140, 100, 200, 80); line(140, 110, 200, 100); line(140, 120, 200, 120); popMatrix(); } boolean saved = false; void draw() { background(0xff000000); float pos = millis() * 0.002; testAALines(pos, pos, 1.0, 0xffffffff); //testLines(pos, pos, 1, 0xffffffff); /* if (!saved) { saveFrame("ogl_custom_aa_lines.png"); saved = true; } */ }