On Wed, 2005-01-19 at 21:29 -0500, Timothy Miller wrote:
> I did a little more experimentation. If you have an antialiased line
> on integer coordinates that's exactly 45 degrees, the center line is
> alpha 1.0. Depending on how you interpret "coverage", this is
> slightly off, because the pixel corners lie slightly outside of the
> line, so you don't have 100% coverage. I'm not sure if I've done the
> math right, but it looks like in that case, the pixel should have 83%
> coverage. However, as the line tends toward vertical or horizontal,
> the given antialias algorithm tends toward expected results, as far as
> I can judge.
I think you are right. Lines near 45 degrees angle appear a little
thick. I also wonder if the algorithm is good enough at the line
endpoints; it doesn't smooth them.
> Also, coverage isn't the only way to compute antialiasing, although
> I'm not sure how much leeway the OpenGL spec gives. If that's really
> a problem, we can compute an attenuation factor based on slope. But I
> don't think it'll be a problem.
The OpenGL isn't that strict about how to implement antialiasing. It
describes the 'ideal' case where exact coverage is square pixels is
computed, but any implemenation is compliant as long as:
- a fragment whose coverage is a subset of the coverage of another
fragment may not have a larger computed coverage than that other
fragment.
- the coverage computation may not depend on the fragment's x and y
value.
See 3.2 of the 1.5 spec.
I'm not sure, but I think your method follows condition 1; it certainly
follows 2.
The glut program below draws lines at various angles using the method
you described; it doesn't look bad at all...
It would be nice to know what algorithm is typically used for
implementing OpenGL width 1.0 smooth lines in hardware.
--ms
#include <GL/glut.h>
#include <cmath>
#include <algorithm>
using namespace std;
const float PI = 3.14159265358979323846;
float ll;
bool hw = false;
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -1, 1);
ll = min(w, h) - 1;
}
void aaline(float v0[2], float v1[2])
{
float x = v1[0] - v0[0];
float y = v1[1] - v0[1];
float l = sqrt(x*x + y*y);
float sx = x / l;
float sy = y / l;
glBegin(GL_TRIANGLE_STRIP);
glColor4f(1, 1, 1, 0);
glVertex2f(v0[0] - sy, v0[1] + sx);
glVertex2f(v1[0] - sy, v1[1] + sx);
glColor4f(1, 1, 1, 1);
glVertex2f(v0[0], v0[1]);
glVertex2f(v1[0], v1[1]);
glColor4f(1, 1, 1, 0);
glVertex2f(v0[0] + sy, v0[1] - sx);
glVertex2f(v1[0] + sy, v1[1] - sx);
glEnd();
}
void aaline2(float v0[2], float v1[2])
{
glBegin(GL_LINES);
glColor4f(1, 1, 1, 1);
glVertex2fv(v0);
glVertex2fv(v1);
glEnd();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case ' ':
hw = hw?false:true;
glutPostRedisplay();
break;
case 'q':
exit(0);
case 'f':
hw = true;
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
glutPostRedisplay();
break;
case 'n':
hw = true;
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glutPostRedisplay();
break;
case 'a':
hw = true;
glDisable(GL_LINE_SMOOTH);
glutPostRedisplay();
break;
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
float v0[2] = { 0.5, 0.5 };
for (int i = 0; i <= 90; ++i) {
float a = i * PI / 180.0;
float v1[2] = { ll * cos(a) + 0.5, ll * sin(a) + 0.5 };
if (hw)
aaline2(v0, v1);
else
aaline(v0, v1);
}
glFlush();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutCreateWindow("aaline");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glClearColor(0, 0, 0, 0);
glColor3f(1, 1, 1);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glutMainLoop();
}
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)