我正在使用Linux中的绘图应用程序(类似于2d cad应用程序),我在使用OpenGL时发现的第一件事就是我的Intel I5 Core HD GMA(内置)图形硬件不支持AA线或多样本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作为换行符,但这对于圆形tectures来说根本不起作用。我也尝试使用OpenGL常见问题解答中显示的GL_MODULATE设置来做这种类型的AA,但没有区别。
非常感谢任何帮助。感谢。
答案 0 :(得分:0)
您不必一次使用整个纹理。让我们假设您的圆形纹理在x轴和y轴上具有从0到1.0的tex顶点。当您需要弯曲边缘或圆形盖子时,可以将(0,0)(0,0.5)(0.5,0.5)(0.5,0)纹理映射到顶点。或者当您只需要线条时,可以将(0.5,0)(0.5,0)(0,0.5)(0,0.5)映射到整个矩形。
答案 1 :(得分:0)
这个的基本实现是绘制1个矩形(你的线)和2个四边形(你的线末端)。
您将半圆纹理放在四边形中,并在矩形中放置一个简单的渐变。
更好的解决方案是绘制一个矩形,并使用段的长度作为V坐标。
在片段着色器中,