Image openGL图像质量(模糊)
我使用openGL创建了一个幻灯片应用程序。不幸的是,与gnome图像查看器相比,使用openGL渲染的图像看起来模糊了 下面是两个截图 (opengl) (图像查看器) 这是基本图像: 图像具有我屏幕的本机大小。(2560x1440)Image openGL图像质量(模糊),image,opengl,sdl,Image,Opengl,Sdl,我使用openGL创建了一个幻灯片应用程序。不幸的是,与gnome图像查看器相比,使用openGL渲染的图像看起来模糊了 下面是两个截图 (opengl) (图像查看器) 这是基本图像: 图像具有我屏幕的本机大小。(2560x1440) 我不确定这是否真的是问题所在,但我认为您不需要/不需要mipmaps。您是否尝试过将而不是gluBuild2DMipmaps与最近邻过滤()结合使用?您遇到的是围栏柱问题的一个变体,它是由OpenGL处理纹理坐标的方式引起的。OpenGL不处理纹理的像素(te
我不确定这是否真的是问题所在,但我认为您不需要/不需要mipmaps。您是否尝试过将而不是
gluBuild2DMipmaps
与最近邻过滤()结合使用?您遇到的是围栏柱问题的一个变体,它是由OpenGL处理纹理坐标的方式引起的。OpenGL不处理纹理的像素(texel),而是使用图像数据作为插值的支持,这实际上比图像像素覆盖的范围更广。因此,纹理坐标0和1不会击中最左/最下和最右/最上的像素,但事实上会更进一步
假设纹理为8像素宽:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
^ ^ ^ ^ ^ ^ ^ ^ ^
0.0 | | | | | | | 1.0
| | | | | | | | |
0/8 1/8 2/8 3/8 4/8 5/8 6/8 7/8 8/8
数字表示纹理的像素,条形表示纹理的边缘,如果是最近的过滤,则表示像素之间的边界。但是,您需要点击像素的中心。所以你对纹理坐标感兴趣
(0/8+1/8)/2=1/(2*8)
(1/8+2/8)/2=3/(2*8)
(7/8+8/8)/2=15/(2*8)
或者更一般地,对于N宽纹理中的像素i,适当的纹理坐标为
(2i+1)/(2N)
但是,如果要将纹理与屏幕像素完全对齐,请记住,指定为坐标的不是四边形的像素,而是边缘,根据投影情况,边缘可能与屏幕像素边缘对齐,而不是中心对齐,因此可能需要其他纹理坐标
请注意,如果您遵循这一点,不管您的过滤模式和mipmap如何,您的图像将始终看起来清晰、清晰,因为插值正好符合您的采样支持,即您的输入图像。切换到另一种过滤模式,如GL_NEAREST,第一眼看上去可能是正确的,但实际上是不正确的,因为它会给您的样本添加别名。所以不要这样做
您的代码中也存在一些其他问题,但它们并不是一个大问题。首先也是最重要的一点是,您选择了一种相当神秘的方式来创建视口维度。您(可能不需要进一步思考)会发现,默认的OpenGL视口是创建上下文时使用的窗口的大小。你使用的是SDL,它有副作用,只要你坚持使用SDL-1,这种方法就不会伤害你。但是,如果切换到任何其他框架,可能会通过代理drawable创建上下文,那么您就会遇到问题 规范的方法通常是从窗口系统(在您的例子中是SDL)检索窗口大小,然后在显示函数的第一个操作中设置视口 另一个问题是使用
gluBuildMipmaps
,因为a)您不想使用mipmaps,b)由于OpenGL-2,您可以上传任意大小的纹理图像(即尺寸不限于2的幂次方),这完全消除了对gluBuildMipmaps的需要。所以不要使用它。只需直接使用glTexImage2D并切换到非mipmapping过滤模式
由于问题更新而更新
计算纹理坐标的方法看起来仍然不正确。看起来你开始数到1了。纹理像素的基索引为0,因此
我会这样做:
假设投影映射视口
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, win_width, 0, win_height, -1, 1);
glViewport(0, 0, win_width, win_height);
我们将纹理坐标计算为
//Do pixel calculatons
glBindTexture( GL_TEXTURE_2D, text);
GLint tex_width, tex_height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_height);
texture_s1 = 1. / (2*width); // (2*0-1
texture_t1 = 1. / (2*height);
texture_s2 = (2.*(tex_width -1) + 1) / (2*width);
texture_t2 = (2.*(tex_height-1) + 1) / (2*height);
请注意,tex_width和tex_height给出了每个方向上的像素数,但坐标是基于0的,因此纹理坐标贴图必须从中减去1。因此,我们也在s1,t1坐标的分子中使用常数1
考虑到你选择的投影,剩下的看起来没问题
glEnable( GL_TEXTURE_2D );
glBegin(GL_QUADS);
glTexCoord2f(s1, t1); //4
glVertex2f(0, 0);
glTexCoord2f(s2, t1); //3
glVertex2f(tex_width, 0);
glTexCoord2f(s2, t2); // 2
glVertex2f(tex_width,tex_height);
glTexCoord2f(s1, t2); // 1
glVertex2f(0,tex_height);
glEnd();
将过滤切换到GL_NEAREST并不能解决OP的问题。这看起来似乎有效,但实际上不起作用。请参阅我的答案以了解解释。嗯,好的:1更改了gl_width=1+((2.0*2560-1)/(2*2560));和高度,以及对公式的偏移量。我还更改为GL_线性glTexParameteri(GL_纹理2D,GL_纹理MAG_过滤器,GL_线性);但与gl_宽度直接比较=2;offset_x=-1使用complexe计算的结果看起来更模糊(但质量非常接近)@aatdark:如果顶点位置正确,您是否也考虑了?您没有设置投影,并且gl_宽度和gl_高度变量在代码中没有实际意义。我建议将GL_投影矩阵设置为glOrtho(0,宽度,0,高度,-1,1),并使用GL_MODELVIEW应用GLTRANSTEF的偏移。好的,我在上面发布了一个更新的源。它又变得模糊了一点。过滤是GL_线性的。我想显示与屏幕分辨率完全相同的图像。我使用了您的代码,但s1=0、t1=0、s2=1、t2=1看起来仍然更好。可能是glTexParameteri(GL_纹理_2D,GL_纹理_MAG_过滤器,GL_线性);这就是问题所在。无论如何,谢谢你的努力;)至少我摆脱了最近的。。
//Do pixel calculatons
glBindTexture( GL_TEXTURE_2D, text);
GLint tex_width, tex_height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_height);
texture_s1 = 1. / (2*width); // (2*0-1
texture_t1 = 1. / (2*height);
texture_s2 = (2.*(tex_width -1) + 1) / (2*width);
texture_t2 = (2.*(tex_height-1) + 1) / (2*height);
glEnable( GL_TEXTURE_2D );
glBegin(GL_QUADS);
glTexCoord2f(s1, t1); //4
glVertex2f(0, 0);
glTexCoord2f(s2, t1); //3
glVertex2f(tex_width, 0);
glTexCoord2f(s2, t2); // 2
glVertex2f(tex_width,tex_height);
glTexCoord2f(s1, t2); // 1
glVertex2f(0,tex_height);
glEnd();