【问题标题】:How can i map textures to objects in legacy OpenGL 1.x?如何将纹理映射到旧版 OpenGL 1.x 中的对象?
【发布时间】:2021-09-06 01:06:30
【问题描述】:

我想绘制一些用于使用 SDL2 和 OpenGL 1.6 的旧软件的指标(因此我现在无法切换到现代 OpenGL)并决定从基本形状构建它们。我已经让绘图逻辑正常工作,但无法让纹理工作。它实际上完全破坏了程序。我想保持一种面向对象的方法,并且能够通过调用一个绘图方法来单独绘制任何对象/形状。

首先我创建了窗口:

void SDLWindow::createWindow(const std::string windowTitle)
{
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        puts("Could not init SDL");
        return;
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);

    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);

    SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);

    Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_ALWAYS_ON_TOP
            | SDL_WINDOW_RESIZABLE;

    this->mainWindow = SDL_CreateWindow(windowTitle.c_str(),
    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->width, this->height,
            flags);

    if (nullptr == mainWindow)
    {
        puts("Window could not be created");
        return;
    }

    this->context = SDL_GL_CreateContext(this->mainWindow);

    if (nullptr == this->context)
    {
        puts("Could not create context");
        return;
    }

    SDL_GL_SetSwapInterval(1);
    SDL_RaiseWindow(this->mainWindow);
}

然后我初始化 OpenGL 细节:

void SDLWindow::initGL()
{
    glClearDepth(1.0f);
    glDepthFunc(GL_LEQUAL);                         // Type Of Depth Testing
//  glEnable(GL_DEPTH_TEST);
    glViewport(0, 0, this->width, this->height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho(0.0f, this->width, this->height, 0.0f, 0.0f, 1.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glEnable(GL_MULTISAMPLE);
}

这些设置是在主应用程序中使用的设置,在我开始添加纹理之前,一切正常。

从文件加载纹理:

void SDLWindow::loadTextureFromFile(char* path){
    SDL_Surface* Surface = SDL_LoadBMP(path);

    glGenTextures(1, &this->textureID);
    glBindTexture(GL_TEXTURE_2D, this->textureID);
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Surface->w, Surface->h, 0, GL_RGB, GL_UNSIGNED_BYTE, Surface->pixels);

    SDL_FreeSurface(Surface);
}

绘制一个带有纹理的原始形状:

void SDLWindow::drawBasicShape()
{
    glBindTexture(GL_TEXTURE_2D, this->textureID); // commented this but doesn't change anything
    glBegin( GL_QUADS);
    glTexCoord2f(0.0f, 0.0f);
    glVertex2f(this->width / 4, this->height / 4);
    glTexCoord2f(1.0f, 0.0f);
    glVertex2f(3 * this->width / 4, this->height / 4);
    glTexCoord2f(1.0f, 1.0f);
    glVertex2f(3 * this->width / 4, 3 * this->height / 4);
    glTexCoord2f(0.0f, 1.0f);
    glVertex2f(this->width / 4, 3 * this->height / 4);
    glEnd();
}

在主循环中,我调用renderRectCore(),它首先加载纹理然后绘制形状:

void SDLWindow::renderRectCore()
{
    //Clear color buffer
    glClear( GL_COLOR_BUFFER_BIT);
//  glColor3f(1.0f, 0.0f, 0.0f);
    glEnable(GL_TEXTURE_2D);

    loadTextureFromFile("D:\Workspace\Eclipse\SDL_test\sample.bmp");
    drawBasicShape();
}

据我所知,加载纹理的函数会以某种方式破坏程序并导致窗口打开空白并立即关闭。删除对loadTextureFromFile 的调用只会绘制白色矩形,但会保持窗口按预期运行。实例化SDLWindow类时,textureID被初始化为0。

【问题讨论】:

  • OpenGL 1 点 6?那从来都不是 OpenGL 版本,it went from 1.5 to 2.0
  • 另外,编辑minimal reproducible example
  • 使用 调试器 查看哪一行代码失败了。但很可能SDL_LoadBMP 返回NULL(文件可能未找到/损坏/不受支持的 BMP 格式),或者它不是 RGB 格式并且数据少于您告诉 GL 读取的数据。

标签: c++ opengl sdl-2 opengl-compat


【解决方案1】:

使用调试器查看失败的代码行。但很可能SDL_LoadBMP 返回NULL 因为

"D:\Workspace\Eclipse\SDL_test\sample.bmp"

不是正确的路径。

您必须正确转义 C++ 字符串文字中的反斜杠字符:

"D:\\Workspace\\Eclipse\\SDL_test\\sample.bmp"

(或者只使用正斜杠,因为它们实际上也受 Windows 支持)。

您的代码也缺乏最基本的错误处理,如果找不到文件或不可读(或不是预期的数据格式),您的代码将崩溃。

【讨论】:

    【解决方案2】:
    glEnable(GL_TEXTURE_2D);
    
    loadTextureFromFile("D:\Workspace\Eclipse\SDL_test\sample.bmp");
    

    在主循环中加载纹理是没有意义的。 将其移至 init。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-03
      • 1970-01-01
      • 2011-05-04
      • 2011-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-22
      相关资源
      最近更新 更多