I am having trouble getting an image texture to render to the screen. Nothing is displayed other than a blank black screen, and there are no obvious errors. I believe the issue has something to do with the glOrtho
call, but i'm not sure.
All relevant code is included below. (OnResize gets called after initialisation and before first Render call)
OpenGL2.1 compatibility required, with a view to add shaders later. The texture stuff being hardcoded to the renderer is just temporary, I already have a texture class ready to go, once I work out what's wrong.
I think I might need a FrameBuffer object somewhere? The tutorials I've found often differ drastically and are usually targeting OGL3
Video::Video() : running(true)
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::string err = "Error initialising video: ";
err += SDL_GetError();
throw std::runtime_error(err);
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED;
this->window = SDL_CreateWindow("lolpenGL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, flags);
if (this->window == nullptr) {
std::string err = "Error creating SDL window: ";
err += SDL_GetError();
throw std::runtime_error(err);
}
this->glcontext = SDL_GL_CreateContext(this->window);
if (this->glcontext == nullptr) {
std::string err = "Error creating GL context: ";
err += SDL_GetError();
throw std::runtime_error(err);
}
GLenum glew_err = glewInit();
if (glew_err != GLEW_OK) {
std::string err = "Error initialising GLEW: ";
err += (char *)glewGetErrorString(glew_err);
throw std::runtime_error(err);
}
if (!GLEW_VERSION_2_1) {
throw std::runtime_error("OpenGL 2.1 not available");
}
int max_tex_size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
if (max_tex_size < 1024) {
throw std::runtime_error("Maximum supported texture size too small");
}
int max_tex_units;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_tex_units);
if (max_tex_units < 2) {
throw std::runtime_error("GPU does not have enough texture unnits");
}
SDL_GL_SetSwapInterval(1); // vsync
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST); // what's drawn last is displayed on top.
// Temp texture load
glGenTextures(1, &this->texid);
glBindTexture(GL_TEXTURE_2D, this->texid);
// Set our texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Load, create texture and generate mipmaps
int width, height;
unsigned char *image = SOIL_load_image("awesomeface.png", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
}
void Video::OnResize(int w, int h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
glOrtho(0, w, 0, h, 9001, -1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void Video::Render()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
{
glColor4f(1, 1, 1, 1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, this->texid);
// do stuff
}
glPopMatrix();
SDL_GL_SwapWindow(this->window);
}
EDIT: Ok, i'm an idiot, I wasn't actually drawing anything. I found that adding the following works, where the // do stuff
is.
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f(0, 0, 0);
glTexCoord2f(0, 1); glVertex3f(0, 100, 0);
glTexCoord2f(1, 1); glVertex3f(100, 100, 0);
glTexCoord2f(1, 0); glVertex3f(100, 0, 0);
glEnd();
Is this the best way to do this?