如何将纹理映射到遗留OpenGL 1.x中的对象



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

一开始我创建窗口:

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:WorkspaceEclipseSDL_testsample.bmp");
drawBasicShape();
}

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

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

"D:WorkspaceEclipseSDL_testsample.bmp"

不是正确的路径。

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

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

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

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

glEnable(GL_TEXTURE_2D);
loadTextureFromFile("D:WorkspaceEclipseSDL_testsample.bmp");

在主循环中加载纹理没有任何意义。将其移动到init。

最新更新