OpenGL + SDL 有时会从坐标中提取

Posted

技术标签:

【中文标题】OpenGL + SDL 有时会从坐标中提取【英文标题】:OpenGL + SDL sometimes draws off from coordinates 【发布时间】:2015-04-04 09:32:21 【问题描述】:

我找不到关于类似问题的问题,所以在长时间的 *** 潜伏者之后,我决定最后问一个问题。我在 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;

【问题讨论】:

好吧,glRasterPos 将使用转换矩阵。但是,您只在初始化期间设置了一次矩阵,因此您在该源代码中报告的行为没有真正的原因。这种转变是如何触发的? 这个绘图事故是在执行程序后随机发生的。一旦发生事故,程序根本不会显示 fps 打印,并且鼠标坐标文本和纹理太高了。通常退出并再次运行程序绘图就可以了。 【参考方案1】:

似乎通过将标志 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);

这个问题可以解决。

【讨论】:

以上是关于OpenGL + SDL 有时会从坐标中提取的主要内容,如果未能解决你的问题,请参考以下文章

带有 OpenGL 4.4 的 SDL2:三角形未正确渲染

使用 OpenGL 和 SDL 处理窗口大小调整

使用像素坐标的 OpenGL 子图像

放大鼠标的算法(OpenGL)

SDL 平台游戏中的 OpenGL 着色器?

OpenGL学习之路——安装