Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image openGL图像质量(模糊)_Image_Opengl_Sdl - Fatal编程技术网

Image openGL图像质量(模糊)

Image openGL图像质量(模糊),image,opengl,sdl,Image,Opengl,Sdl,我使用openGL创建了一个幻灯片应用程序。不幸的是,与gnome图像查看器相比,使用openGL渲染的图像看起来模糊了 下面是两个截图 (opengl) (图像查看器) 这是基本图像: 图像具有我屏幕的本机大小。(2560x1440) 我不确定这是否真的是问题所在,但我认为您不需要/不需要mipmaps。您是否尝试过将而不是gluBuild2DMipmaps与最近邻过滤()结合使用?您遇到的是围栏柱问题的一个变体,它是由OpenGL处理纹理坐标的方式引起的。OpenGL不处理纹理的像素(te

我使用openGL创建了一个幻灯片应用程序。不幸的是,与gnome图像查看器相比,使用openGL渲染的图像看起来模糊了

下面是两个截图

(opengl)

(图像查看器)

这是基本图像:

图像具有我屏幕的本机大小。(2560x1440)


我不确定这是否真的是问题所在,但我认为您不需要/不需要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();