1

私はopenGLを使ってスライドショーアプリを作成しています。残念ながら、openGL でレンダリングされた画像は、gnome 画像ビューアーに比べてぼやけて見えます。

ここに2つのスクリーンショットがあります

(opengl) http://tinyurl.com/dxmnzpc

(画像ビューア) http://tinyurl.com/8hshv2a

これが基本イメージです: http://tinyurl.com/97ho4rp

画像は私の画面のネイティブサイズです。(2560×1440)

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/freeglut.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <unistd.h>

GLuint text = 0;

GLuint load_texture(const char* file) {
        SDL_Surface* surface = IMG_Load(file);

        GLuint texture;
        glPixelStorei(GL_UNPACK_ALIGNMENT,4);
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
        SDL_PixelFormat *format = surface->format;
        printf("%d %d \n",surface->w,surface->h);
        if (format->Amask) {
                gluBuild2DMipmaps(GL_TEXTURE_2D, 4,surface->w, surface->h, GL_RGBA,GL_UNSIGNED_BYTE, surface->pixels);
        } else {
                gluBuild2DMipmaps(GL_TEXTURE_2D, 3,surface->w, surface->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);
        }
        SDL_FreeSurface(surface);

        return texture;
}

void display(void) {
        GLdouble offset_x = -1;
        GLdouble offset_y = -1;

        int p_viewport[4];
        glGetIntegerv(GL_VIEWPORT, p_viewport); 

        GLfloat gl_width = p_viewport[2];//width(); // GL context size
        GLfloat gl_height = p_viewport[3];//height();

        glClearColor (0.0,2.0,0.0,1.0);
        glClear (GL_COLOR_BUFFER_BIT);

        glLoadIdentity();
        glEnable( GL_TEXTURE_2D );
        glTranslatef(0,0,0);

        glBindTexture( GL_TEXTURE_2D, text);

        gl_width=2; gl_height=2;

        glBegin(GL_QUADS);
        glTexCoord2f(0, 1); //4
        glVertex2f(offset_x, offset_y);

        glTexCoord2f(1, 1); //3
        glVertex2f(offset_x + gl_width, offset_y);

        glTexCoord2f(1, 0); // 2
        glVertex2f(offset_x + gl_width, offset_y + gl_height);

        glTexCoord2f(0, 0); // 1
        glVertex2f(offset_x, offset_y + gl_height);
        glEnd();

        glutSwapBuffers();
}


int main(int argc, char **argv) {
        glutInit(&argc,argv);
        glutInitDisplayMode (GLUT_DOUBLE);

        glutGameModeString("2560x1440:24");
        glutEnterGameMode();       
        text = load_texture("/tmp/raspberry/out.jpg");

        glutDisplayFunc(display);
        glutMainLoop();
}

更新された試行

void display(void)                                                                                                         
{                                                                                                                          
        GLdouble texture_x = 0;                                                                                            
        GLdouble texture_y = 0;                                                                                            
        GLdouble texture_width = 0;                                                                                        
        GLdouble texture_height = 0;                                                                                       

        glViewport(0,0,width,height);                                                                                      

        glClearColor (0.0,2.0,0.0,1.0);                                                                                    
        glClear (GL_COLOR_BUFFER_BIT);                                                                                     
        glColor3f(1.0, 1.0, 1.0);                                                                                          

        glMatrixMode(GL_PROJECTION);                                                                                       
        glLoadIdentity();                                                                                                  
        glOrtho(0, width, 0, height, -1, 1);                                                                               

        //Do pixel calculatons                                                                                             
        texture_x = ((2.0*1-1) / (2*width));                                                                               
        texture_y = ((2.0*1-1) / (2*height));                                                                              
        texture_width=((2.0*width-1)/(2*width));                                                                           
        texture_height=((2.0*height-1)/(2*height));                                                                        

        glMatrixMode(GL_MODELVIEW);                                                                                        
        glLoadIdentity();                                                                                                  
        glTranslatef(0,0,0);                                                                                               

        glEnable( GL_TEXTURE_2D );                                                                                         
        glBindTexture( GL_TEXTURE_2D, text);                                                                               

        glBegin(GL_QUADS);                                                                                                 
        glTexCoord2f(texture_x, texture_height); //4                                                                       
        glVertex2f(0, 0);                                                                                                  

        glTexCoord2f(texture_width, texture_height); //3                                                                   
        glVertex2f(width, 0);                                                                                              

        glTexCoord2f(texture_width, texture_y); // 2                                                                       
        glVertex2f(width,height);                                                                                          

        glTexCoord2f(texture_y, texture_y); // 1                                                                           
        glVertex2f(0,height);                                                                                              
        glEnd();                                                                                                           

        glutSwapBuffers();                                                                                                 
}     
4

2 に答える 2

3

遭遇するのは、OpenGLがテクスチャ座標を処理する方法から生じるフェンスポスト問題のバリエーションです。OpenGLは、テクスチャのピクセル(テクセル)をアドレス指定しませんが、補間のサポートとして画像データを使用します。これは、実際には、画像のピクセルよりも広い範囲をカバーします。したがって、テクスチャ座標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)

ただし、テクスチャを画面のピクセルと完全に位置合わせする場合は、座標として指定するのはクワッドのピクセルではなく、投影によっては中心ではなく画面のピクセルのエッジと位置合わせされる可能性があるため、他のテクスチャが必要になる可能性があることに注意してください。座標。

これに従うと、フィルタリングモードやミップマップに関係なく、補間が入力画像であるサンプリングサポートに正確にヒットするため、画像は常に鮮明で鮮明に見えることに注意してください。GL_NEARESTのような別のフィルタリングモードに切り替えると、一見正しく見えるかもしれませんが、サンプルのエイリアスになるため、実際には正しくありません。だからそれをしないでください。


コードには他にもいくつかの問題がありますが、それほど大きな問題ではありません。何よりもまず、ビューポートの寸法を表示するためのかなり難解な方法を選択しています。あなたは(おそらくそれ以上考えずに)デフォルトのOpenGLビューポートがコンテキストが作成されたウィンドウのサイズであるという事実を利用しています。SDLを使用している場合、SDL-1を使用している限り、このアプローチで問題が発生することはありません。ただし、プロキシドローアブルを介してコンテキストを作成する可能性のある他のフレームワークに切り替えると、問題が発生します。

通常の方法は、ウィンドウシステム(この場合はSDL)からウィンドウサイズを取得し、表示機能の最初のアクションの1つにビューポートを設定することです。

もう1つの問題は、の使用ですgluBuildMipmaps。これは、a)ミップマップを使用したくない場合とb)OpenGL-2以降、任意のサイズのテクスチャ画像をアップロードできるため(つまり、次元の2の累乗に制限されないため)、 gluBuildMipmapsの必要性を完全に排除します。したがって、使用しないでください。glTexImage2Dを直接使用して、非ミップマッピングフィルタリングモードに切り替えるだけです。

質問の更新による更新

テクスチャ座標を計算する方法はまだ正しく見えません。1から数え始めているようです。テクスチャピクセルは0ベースのインデックスが付けられているので、…</ p>

これは私がそれをする方法です:

投影がビューポートをマップすると仮定します

    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();
于 2012-08-08T13:20:12.017 に答える
0

これが本当に問題なのかどうかはわかりませんが、ここではミップマップは必要ない/欲しくないと思います。最近傍フィルタリング ( /glTexImage2D ) と組み合わせて使用​​する代わりに使用してみましたか?gluBuild2DMipmapsglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MINMAG_FILTER, GL_NEAREST);

于 2012-08-07T13:00:47.837 に答える