Last week I bought an old OpenGL book (OpenGL superbible designed for Windows 95) for a dollar thinking I could get some of the ideas of drawing in 3D and OpenGL. All of the code uses this weird windows library so I’ve been porting the examples to SDL OpenGL. I’m stuck on a resizable windowed example where a square is drawn in the center no matter what size the window is. For some reason the square only shows up on the first resize and after that I don’t see it again no matter how I resize the window.
Does anybody know what the problem is?
#include <stdio.h>
#include <stdlib.h>
#include "SDL.h"
#include "SDL_opengl.h"
#define TRUE 1
#define FALSE 0
#define WIN_WIDTH 500
#define WIN_HEIGHT 400
#define BPP 32
//go through and get the values to see if everything was set
int check_gl_init(int r_size, int g_size, int b_size, int dbuff) {
int red, green, blue, doublebuf;
SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &red);
if(red != r_size) { return FALSE; }
SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &green);
if(green != g_size) { return FALSE; }
SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &blue);
if(blue != b_size) { return FALSE; }
SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuf);
if(dbuff != doublebuf) { return FALSE; }
return TRUE;
}
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_EVERYTHING);
atexit(SDL_Quit);
SDL_Surface* screen;
SDL_Event e;
int w = WIN_WIDTH; int h = WIN_HEIGHT;
Uint32 vid_flags = SDL_OPENGL | SDL_RESIZABLE;
if(SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8) < 0) { printf("opengl error: %s\n", SDL_GetError()); }
if(SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8) < 0) { printf("opengl error: %s\n", SDL_GetError()); }
if(SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8) < 0) { printf("opengl error: %s\n", SDL_GetError()); }
if(SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8) < 0) { printf("opengl error: %s\n", SDL_GetError()); }
if(SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32) < 0) { printf("opengl error: %s\n", SDL_GetError()); }
if(SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) < 0) {
printf("couldn't set double buffering: %s\n", SDL_GetError());
} else { vid_flags |= SDL_DOUBLEBUF; }
const SDL_VideoInfo* info = SDL_GetVideoInfo();
if(info->hw_available == TRUE) { vid_flags |= SDL_HWSURFACE; } else { vid_flags |= SDL_SWSURFACE; }
printf("hardware surfaces available?: %s\n", (info->hw_available == TRUE ? "yes" : "no"));
if(info->blit_hw == TRUE) { vid_flags |= SDL_HWACCEL; }
printf("hardware blits available?: %s\n", (info->blit_hw == TRUE ? "yes" : "no"));
if(SDL_VideoModeOK(WIN_WIDTH, WIN_HEIGHT, BPP, vid_flags) == 0) {
printf("error: video mode not supported: `%s'\n", SDL_GetError());
return 0;
}
else {
screen = SDL_SetVideoMode(WIN_WIDTH, WIN_HEIGHT, BPP, vid_flags);
if(screen == NULL) {
printf("no video: `%s'\n", SDL_GetError());
return 0;
}
}
if(check_gl_init(BPP / 4, BPP / 4, BPP / 4, TRUE) == FALSE) {
printf("problem setting up opengl: %s\n", glGetString(glGetError()));
return 0;
}
int running = TRUE;
for(;running;) {
//process events
while(SDL_PollEvent(&e)) {
if(e.type == SDL_VIDEORESIZE) {
w = e.resize.w; h = e.resize.h;
if(h == 0) { h = 1; } //prevent division by zero
screen = SDL_SetVideoMode(w, h, BPP, vid_flags);
if(screen == NULL) {
printf("sdl error, screen died: `%s'\n", SDL_GetError());
}
glViewport(0, 0, w, h); //x, y, w, h
glLoadIdentity(); //reset coordinate system
glMatrixMode(GL_PROJECTION);
if(w <= h) {
glOrtho(0.0f, 250.0f, 0.0f, 250.0f * (h / w), 1.0, -1.0);
}
else {
glOrtho(0.0f, 250.0f * (w / h), 0.0f, 250.0f, 1.0, -1.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(glGetError() != GL_NO_ERROR) {
printf("opengl error: %s\n", glGetString(glGetError()));
}
}
if(e.type == SDL_QUIT) { running = FALSE; }
if(e.type == SDL_KEYDOWN) { if(e.key.keysym.sym == SDLK_q) { running = FALSE; } }
}
glClearColor(0.0f, 0.0f, 1.0f, 1.0f); //clear with blue
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f); //red
glRectf(100.0f, 150.0f, 150.0f, 100.0f);
glFlush();
SDL_GL_SwapBuffers();
SDL_Delay(100);
}
SDL_Quit();
return 0;
}
You have this:
That sequence will load the identity matrix on to the
GL_MODELVIEWstack, since that was the most recent stack set viaglMatrixMode()during the last resize.glOrtho()then goes on to multiply a new ortho projection matrix by the last one. As you saw this doesn’t work very well.Set your matrix mode, then load the identity matrix: