OpenGL + SDL 有时会偏离坐标

OpenGL + SDL sometimes draws off from coordinates

我找不到关于类似问题的问题,所以在长时间潜伏在 Whosebug 之后,我决定终于问一个问题。我在 Ubuntu 14.04 LTS 上使用 SDL + OpenGL 时遇到的问题是,有时当我在屏幕上绘制纹理和文本时,坐标有点偏离。我这里有一张图片显示了正确的绘图方式(程序打开全屏但我剪裁了图片)

下面是纹理和文本的绘制有时如何显示

如您所见,此处未显示 fps 文本,鼠标坐标和纹理也太高了。无论如何,当我将鼠标移到左上角时,显示的坐标应该是 0,0。

下面是我用来绘制的代码

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_opengl.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <sstream>
#include <iostream>

#define WINDOW_WIDTH 1366
#define WINDOW_HEIGHT 768


void drawText(const float x, const float y, const std::string text){

    int i;

    glColor4f(1.0, 1.0, 1.0, 1.0);
    glRasterPos2f(x,y);
    glDisable(GL_TEXTURE);
    glDisable(GL_TEXTURE_2D);

    for(i=0; i<text.length(); ++i){
        glutBitmapCharacter(GLUT_BITMAP_9_BY_15, (int)text.at(i));
    }

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_TEXTURE);

}

int main(int argc, char* argv[]){

    SDL_Window* window = NULL;
    SDL_GLContext context;
    SDL_Surface* image = NULL;
    SDL_Event event;

    GLuint        texture;
    const Uint8  *keyState;
    Uint32        mouseState;

    bool               run        = true;
    unsigned long int  frameCount = 0;
    unsigned long int  lastTicks  = 0;
    unsigned short int fps        = 0;
    int                mouseX     = 0;
    int                mouseY     = 0;

    std::stringstream buffer;
    std::stringstream mouseCoords;

    if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        printf("SDL_Error 1: %s\n", SDL_GetError());
        exit(1);
    }

    glutInit(&argc, NULL);

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    window = SDL_CreateWindow("SDL 2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);

    if (window == NULL) {
        printf("SDL_Error 2: %s\n", SDL_GetError());
        exit(1);
    }

    image = SDL_LoadBMP("resources/images/test.bmp");
    context = SDL_GL_CreateContext(window);

    gluOrtho2D(0.0f, (float)WINDOW_WIDTH, (float)WINDOW_HEIGHT, 0.0f);

    glEnable(GL_TEXTURE_2D);

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, image->format->BytesPerPixel, image->w, image->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    while(run){

        glClear(GL_COLOR_BUFFER_BIT);

        glBindTexture(GL_TEXTURE_2D, texture);
        glBegin(GL_QUADS);
            glTexCoord2f(0.0f, 0.0f);
            glVertex2f(10.0f, 50.0f);
            glTexCoord2f(1.0f, 0.0f);
            glVertex2f(74.0f, 50.0f);
            glTexCoord2f(1.0f, 1.0f);
            glVertex2f(74.0f, 114.0);
            glTexCoord2f(0.0f, 1.0f);
            glVertex2f(10.0f, 114.0f);
        glEnd();

        keyState   = SDL_GetKeyboardState(NULL);
        mouseState = SDL_GetMouseState(&mouseX, &mouseY);

        while(SDL_PollEvent(&event)){
            switch(event.type){
                case SDL_QUIT:
                    run = false;
                break;
            }
        }

        if(keyState[SDL_SCANCODE_ESCAPE]){
            run = false;
        }

        mouseCoords << "mouseCoords=";
        mouseCoords << mouseX;
        mouseCoords << ",";
        mouseCoords << mouseY;

        ++frameCount;

        if(SDL_GetTicks()-lastTicks >= 1000){
            fps        = frameCount;
            frameCount = 0;
            lastTicks  = SDL_GetTicks();
        }

        buffer << "fps=";
        buffer << fps;
        drawText(10, 20, buffer.str());
        drawText(10, 40, mouseCoords.str());
        mouseCoords.str("");
        buffer.str("");

        SDL_GL_SwapWindow(window);
    }

    glDeleteTextures(1, &texture);  
    SDL_FreeSurface(image);
    SDL_GL_DeleteContext(context);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

似乎通过将标志 SDL_WINDOW_BORDERLESS 添加到 SDL_CreateWindow() 函数调用,问题就消失了。

所以通过修改行

window = SDL_CreateWindow("SDL 2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);

到这个格式

window = SDL_CreateWindow("SDL 2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL);

这个问题可以解决。