Я работаю над приложением для рисования (похожим на приложение 2d cad) в Linux, и одна из первых вещей, которые я обнаружил при работе с OpenGL, это то, что мое графическое оборудование Intel I5 Core HD GMA (встроенное) не поддерживает AA-линии или мультисэмплированные AA-методы. Итак, я провел последнюю неделю или около того, исследуя, как сделать сглаживание с помощью текстур. Я наткнулся на статью об арекусу Invariance Texture AA и довольно многое понял из нее, но проблема, с которой я столкнулся, заключается в том, что когда я использую смешанный круг, как во многих примерах, мои линии получаются очень широкими эллипсами. Это действительно смешивается, и эллипс выглядит великолепно. :) Однако, это не совсем то, что я ищу. Похоже, что текстура не «размывается» по горизонтали, а вместо этого растягивается. Я получаю эллипс, который является высотой «ширины» моей линии и эллиптической ширины примерно на 1/2 длины моей линии.
Тем временем я попробовал что-то немного другое и создал текстуру шириной 1 пиксель и высотой X пикселей. Как и ожидалось, высота и изменяющиеся значения альфа меняют результат моих линий, но на самом деле я получаю довольно хорошие результаты, за исключением очень тонких линий.
Я включаю код для небольшого тестового приложения, которое я использую (приложение GLUT), в надежде, что кто-то может указать на глупую ошибку, которую я делаю. Он использует вышеупомянутую текстуру шириной в 1 пиксель, но, очевидно, я хочу заменить ее круглой текстурой. Он не предназначен для того, чтобы быть самым эффективным кодом, но с ним легко играть, пока я не смогу все уладить.
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
float centerX = 320.0;
float centerY = 240.0;
GLuint textureId = 0;
static GLuint createTexture(int width, int height)
{
GLuint id;
glGenTextures( 1, &id );
glBindTexture( GL_TEXTURE_2D, id );
int bpp = 4; // Bytes per pixel
GLubyte* bitmap = new GLubyte[width * height * bpp];
for (int y = 0; y < height; y++) {
printf("%03d: ",y);
for (int x = 0; x < width; x++) {
if ((y == 0) || (y == height - 1)) {
bitmap[y * width * bpp + x + 3] = 21;
} else if ((y == 1) || (y == height - 2)) {
bitmap[y * width * bpp + x + 3] = 80;
} else if ((y == 2) || (y == height - 3)) {
bitmap[y * width * bpp + x + 3] = 166;
} else {
bitmap[y * width * bpp + x + 3] = 255;
}
printf("%03d ", bitmap[y * width * bpp + x + 3]);
// Fill color with white so we can blend in our
// own color when we draw the line.
bitmap[y * width * bpp + x + 0] = 255;
bitmap[y * width * bpp + x + 1] = 255;
bitmap[y * width * bpp + x + 2] = 255;
}
printf("\n");
}
glTexImage2D(GL_TEXTURE_2D, 0, bpp, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, bitmap);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Doesn't seem to make much difference for how this is currently
// working.
// gluBuild2DMipmaps( GL_TEXTURE_2D, 4, width, height,
// GL_RGBA, GL_UNSIGNED_BYTE, bitmap);
delete [] bitmap;
return id;
}
static void resize(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,width,height,0,1.0,-1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
centerX = (float)width / 2.0;
centerY = (float)height / 2.0;
}
static void drawLine(float x0, float y0, float x1, float y1, float width)
{
glBindTexture(GL_TEXTURE_2D, textureId);
// Would be faster using arrays, but this is easier to tweak for now
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f( x0, y0);
glTexCoord2f(0.0, 1.0); glVertex2f(x0, y0 + width);
glTexCoord2f(1.0, 1.0); glVertex2f(x1, y1 + width);
glTexCoord2f(1.0, 0.0); glVertex2f(x1, y1);
glEnd();
}
static void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for(float angle = 0.0; angle < 360.0; angle += 2.0) {
glPushMatrix();
glTranslatef(centerX, centerY, 0.0);
glRotatef(angle, 0.0, 0.0, 1.0);
glColor3f(0.0, 0.3, 0.9);
drawLine(0.0, 0.0, centerY, 0.0, 5.0);
glPopMatrix();
}
glFlush();
glutSwapBuffers();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Texture Antialiasing");
glutReshapeFunc(resize);
glutDisplayFunc(display);
glClearColor(1,1,1,1);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glEnable(GL_COLOR_MATERIAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// Create a texture 1 pixel wide by 8 pixels high. This
// texture will get stretched horizontally when we
// draw the textured line. Ideally, we would want to use
// a circlular texture here, but the code currently causes
// the line to consist of a very wide ellipse with "width"
// height and a elliptical width of about 1/2 our line length.
textureId = createTexture(1,8);
glutMainLoop();
return EXIT_SUCCESS;
}
Я пробовал разные варианты вызовов glTexParameterf, например, пытался использовать GL_NEAREST для фильтров и GL_REPEAT для обтекания, но это не сработало совсем для круговых структур. Я также пытался использовать параметр GL_MODULATE, как показано в FAQ по OpenGL, для выполнения этого типа AA, но это не имело никакого значения.
Любая помощь будет высоко ценится. Благодаря.