【发布时间】:2011-05-19 03:27:11
【问题描述】:
我正在 Linux 中开发一个绘图应用程序(类似于 2d cad 应用程序),我在使用 OpenGL 时发现的第一件事是我的 Intel I5 Core HD GMA(内置)图形硬件不支持AA 线或 Multisample AA 方法。所以,我花了大约一周的时间研究如何使用纹理进行抗锯齿。我遇到了 arekkusu Invariance Texture AA 文章,并从中学到了很多,但我遇到的问题是,当我像许多示例中那样使用混合圆时,我的线条会变成非常宽的椭圆。它确实混合正确,椭圆看起来很棒。 :) 但是,这并不是我想要的。看起来纹理没有被水平“涂抹”,而是被拉伸。我最终得到一个椭圆,它是我的线条“宽度”的高度和一个大约是我线条长度的 1/2 的椭圆宽度。
与此同时,我尝试了一些稍微不同的方法,并创建了一个 1 像素宽和 X 像素高的纹理。正如预期的那样,高度和不同的 alpha 值确实会改变我的线条的结果,但实际上我得到了非常好的结果,除了非常细的线条。
我正在包含我正在使用的一个小型测试应用程序(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 用于包装,但这对于圆形结构来说根本不起作用。我也尝试使用 OpenGL 常见问题解答中所示的 GL_MODULATE 设置来执行这种类型的 AA,但这没有任何区别。
任何帮助将不胜感激。谢谢。
【问题讨论】:
标签: opengl textures antialiasing