2017-01-01 56 views
1

我想製作一個內部爲320x240的遊戲,但呈現在屏幕上的整數倍(640x480,960,720等)。我正在尋找復古的2D像素圖形。OpenGL規模單像素線

我已通過經由glOrtho()設置內部分辨率實現此:

glOrtho(0, 320, 240, 0, 0, 1); 

然後我擴大由3倍的輸出分辨率,這樣的:

glViewport(0,0,960,720); 
window = SDL_CreateWindow("Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 960, 720, SDL_WINDOW_OPENGL); 

我畫這樣的矩形:

glBegin(GL_LINE_LOOP); 
glVertex2f(rect_x, rect_y); 
glVertex2f(rect_x + rect_w, rect_y); 
glVertex2f(rect_x + dst_w, dst_y + dst_h); 
glVertex2f(rect_x, rect_y + rect_h); 
glEnd(); 

它可以在320x240下完美工作(未縮放):

enter image description here

當我擴展到960x720,像素渲染所有的作品就好了!然而,GL_Line_Loop似乎並未在320x240的畫布上繪製,而是放大了,但是繪製在最終的960x720畫布上。其結果是在3px的世界:(

enter image description here

如何畫線的320×240 glOrtho帆布1px的線條,而不是960x720輸出印刷品嗎?

+1

如果FBO不是你的場景,總會有[使用三角形的DIY寬線條](http://stackoverflow.com/a/3058978/44729)。 – genpfault

回答

1

正如我在我的評論中提到的英特爾OpenGL驅動程序有直接呈現到紋理的問題,我不知道任何正在工作的解決方法。在這種情況下,唯一的解決方法是使用glReadPixels將屏幕內容複製到CPU內存中,然後將其複製回GPU作爲紋理。粗糙的要比直接渲染紋理要慢得多。因此,這裏的交易:

  1. 設置低分辨率查看

    不改變你的窗口剛剛glViewport值的分辨率。然後呈現在低分辨率的場景(在短短的屏幕空間的一小部分)

  2. 副本渲染畫面變成質地

  3. 設定目標分辨率視圖
  4. 渲染紋理

    不要忘記使用GL_NEAREST過濾器。最重要的是,只有在此之前,才交換緩衝區!否則你會閃爍。

這裏C++的這一來源:

void gl_draw() 
    { 
    // render resolution and multiplier 
    const int xs=320,ys=200,m=2; 

    // [low res render pass] 
    glViewport(0,0,xs,ys); 
    glClearColor(0.0,0.0,0.0,1.0); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glDisable(GL_DEPTH_TEST); 
    glDisable(GL_TEXTURE_2D); 
    // 50 random lines 
    RandSeed=0x12345678; 
    glColor3f(1.0,1.0,1.0); 
    glBegin(GL_LINES); 
    for (int i=0;i<100;i++) 
    glVertex2f(2.0*Random()-1.0,2.0*Random()-1.0); 
    glEnd(); 

    // [multiply resiolution render pass] 
    static bool _init=true; 
    GLuint txrid=0;  // texture id 
    BYTE map[xs*ys*3];  // RGB 
    // init texture 
    if (_init)    // you should also delte the texture on exit of app ... 
     { 
     // create texture 
     _init=false; 
     glGenTextures(1,&txrid); 
     glEnable(GL_TEXTURE_2D); 
     glBindTexture(GL_TEXTURE_2D,txrid); 
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST); // must be nearest !!! 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST); 
     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_COPY); 
     glDisable(GL_TEXTURE_2D); 
     } 
    // copy low res screen to CPU memory 
    glReadPixels(0,0,xs,ys,GL_RGB,GL_UNSIGNED_BYTE,map); 
    // and then to GPU texture 
    glEnable(GL_TEXTURE_2D); 
    glBindTexture(GL_TEXTURE_2D,txrid);   
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xs, ys, 0, GL_RGB, GL_UNSIGNED_BYTE, map); 
    // set multiplied resolution view 
    glViewport(0,0,m*xs,m*ys); 
    glClear(GL_COLOR_BUFFER_BIT); 
    // render low res screen as texture 
    glBegin(GL_QUADS); 
    glTexCoord2f(0.0,0.0); glVertex2f(-1.0,-1.0); 
    glTexCoord2f(0.0,1.0); glVertex2f(-1.0,+1.0); 
    glTexCoord2f(1.0,1.0); glVertex2f(+1.0,+1.0); 
    glTexCoord2f(1.0,0.0); glVertex2f(+1.0,-1.0); 
    glEnd(); 
    glDisable(GL_TEXTURE_2D); 

    glFlush(); 
    SwapBuffers(hdc); // swap buffers only here !!! 
    } 

和預覽:

preview

我測試了一些英特爾HD顯卡(天曉得這版本)我得到了我的dis posal和它的作品(雖然標準渲染紋理方法不是)。

7

沒有「320×240 glOrtho帆布」 。只有窗口的實際分辨率是:960x720。

你所做的只是放大你渲染的圖元的座標,所以,你的代碼表示渲染一行,例如(20,20)到(40,40),並且OpenGL(最終)在每個維度上將這些座標縮放3:(60,60)和(120x120)。

但是,這只是處理終點。中間發生的事情仍然基於您正在以窗口的實際分辨率進行渲染的事實。

即使您僱用了glLineWidth來更改線條的寬度,那隻會修正線條寬度。它不能解決這樣的事實,即線條的光柵化基於您渲染的實際分辨率。所以對角線不會有你想要的像素化外觀。

正確做到這一點的唯一方法就是,正確地做到這一點。渲染到實際320x240的圖像,然後將其繪製到窗口的實際分辨率。

您必須創建該尺寸的紋理,然後將其附加到framebuffer object。綁定FBO進行渲染並渲染(視口設置爲圖像大小)。然後解除綁定FBO,然後將該紋理繪製到窗口(將視口設置爲窗口的分辨率)。

+0

是的我同意但需要添加,如果你要渲染紋理,你可以預期,英特爾gfx卡將無法按預期工作,或根本不工作,直到他們修復了舊的gfx卡從未基於經驗的驅動程序...在這種情況下,你可以嘗試'glReadPixels'而不是... – Spektre

+0

@Spektre:如果你想添加一個討論特定驅動程序錯誤的答案,請隨意。我不知道你說的是哪個漏洞,或者你指的是哪個硬件,所以我沒有資格討論它。 –

+1

我添加了緩慢的** OpenGL 1.0 **方法,即使在英特爾上也是如此。 – Spektre