Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411629 Posts in 69392 Topics- by 58447 Members - Latest Member: sinsofsven

May 11, 2024, 01:53:56 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)OpenGL initialisation in SDL
Pages: [1]
Print
Author Topic: OpenGL initialisation in SDL  (Read 3621 times)
Tycho Brahe
Level 10
*****

λx.x


View Profile
« on: January 07, 2010, 12:35:00 PM »

I need help initialising opengl in SDL, thusfar I have some code from a nehe tutorial which will create a window within which is fine for rendering, assuming you want to render bettween the z values -1 and 1.

I'm using this code to initialise opengl and create the SDL window:
Code:
if( SDL_Init( SDL_INIT_VIDEO ) != 0 )
{
  return false;
}
//all values are "at least"!
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// Set the title.
SDL_WM_SetCaption(title, title);
// Flags tell SDL about the type of window we are creating.
int flags = SDL_OPENGL;
if(fullscreen == true)
{
flags |= SDL_FULLSCREEN;
}
// Create the window
SDL_Surface * screen = SDL_SetVideoMode( width, height, bpp, flags);

if(screen == 0)
{
return false;
}
//SDL doesn't trigger off a ResizeEvent at startup, but as we need this for OpenGL, we do this ourself[img][/img]
SDL_Event resizeEvent;
resizeEvent.type = SDL_VIDEORESIZE;
resizeEvent.resize.w = width;
resizeEvent.resize.h = height;

SDL_PushEvent(&resizeEvent);

this creates a window which looks like this (I've got a square being with centre (0,0,0)) (ignore this bit at the bottom right):


Does anyone have any tried and tested code which will create a opengl rendering context with full 3d,and scaled so that a square will be a square in a rectangular window, as opposed to a rectangle as it is in my example...

Thanks in advance...
Logged
LemonScented
Level 7
**



View Profile
« Reply #1 on: January 07, 2010, 01:57:32 PM »

The code you've got looks fine to me - I've just checked it against my own SDL OpenGL code and it looks fine. What does your code look like that sets up (or resets) the openGL projection matrix when you get a resize event? Should be something along the lines of:
Code:
void ResizeWindow(s32 width, s32 height)
{
if (height == 0)
{
height = 1;
}

glViewport(0, 0, width, height); // Reset The Current Viewport

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

float FOV = 50.0f;
float zNear = 1.0f;
float zFar = 500.0f;
gluPerspective(FOV , (GLfloat)width/(GLfloat)height, zNear , zFar);
   
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();x
}
Logged

powly
Level 4
****



View Profile WWW
« Reply #2 on: January 07, 2010, 02:16:50 PM »

Oh sorry, took me a while to notice this.

This is my normal SDL/OGL window init code.

Code:
int w = 640, h = 480, bpp = 32;
bool full = false;
double fov = 80.0, znear = 1.0, zfar = 100.0, pi = 3.14159265358979323;

putenv("SDL_VIDEO_CENTERED=true");
SDL_WM_SetCaption("Title", NULL);

SDL_SetVideoMode(w, h, bpp, SDL_OPENGL|full*SDL_FULLSCREEN);

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

double fw, fh;

fw = tan((fov/360.0)*pi)*znear;
fh = (float(h)/float(w))*fw;

glFrustum(-fw, fw, -fh, fh, znear, zfar);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

I don't like using glu for only one function, so I use glFrustum instead of gluPerspective - it takes a few calculations, but that's quite simple trigonometry. NeHe has a nice code snippet and a little explanation on this here.

I've never feeled the need to let people resize my windows during runtime, so I don't have any resize code. And I don't use setattributes that much, you get the most suitable settings anyways (I've never seen the defaults fail in any way, even though the documentation says it might happen) Well, for antialiasing set SDL_GL_MULTISAMPLEBUFFERS to 1 and SDL_GL_MULTISAMPLESAMPLES to 2, 4 or 8.

After all this, you can just draw away, remember to keep your coordinates negative, though, the almighty OpenGL camera looks down the negative z axis.
Logged
mcc
Level 10
*****


glitch


View Profile WWW
« Reply #3 on: January 07, 2010, 09:08:26 PM »

So it works for you, the only thing you haven't figured out is how to get the aspect ratio set up such that a square is "square"?

You can see the full code I use in the link in my sig, but what I like to do is something like:

Code:
double aspect;
int fullscreenw = 0, fullscreenh = 0;
int surfacew = 0, surfaceh = 0;

void sdl_surface_init(bool in_a_window)
{
if (!(fullscreenw || fullscreenh)) {
const SDL_VideoInfo *video = SDL_GetVideoInfo();
fullscreenw = video->current_w; fullscreenh = video->current_h;
ERR("Screen resolution is: %d,%d\n", fullscreenw, fullscreenh);
}

SDL_Surface *surface;

if (in_a_window)
surface = SDL_SetVideoMode(
600.0*fullscreenw/fullscreenh, 600, 0, // So for example this will be 800x600 on a 1024x768 screen.
SDL_OPENGL);
else
surface = SDL_SetVideoMode(
fullscreenw, fullscreenh, 0, SDL_FULLSCREEN |
SDL_OPENGL);

  if (surface  == NULL ) {
    REALERR("Unable to create OpenGL screen: %s\n", SDL_GetError());
Quit(2);
  }
 
  aspect = double(surface->h)/surface->w;
  surfacew = surface->w; surfaceh = surface->h;
 
  ERR("Window size %dx%d ratio %lf\n", surface->w, surface->h, aspect);
 
  SDL_WM_SetCaption(NAME_OF_THIS_PROGRAM, NULL);
}

Incidentally you can call that function multiple times with different in_a_window arguments to enter and leave windowed mode.

What's nice about this way of doing it is it leaves you with the window having the same aspect ratio as the screen; and it also leaves you with this "aspect" variable that gives you the ratio between the window's width and height, so you can use that later to scale the screen and "make squares square":

Code:
void goOrtho() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1.0, 5.0);
glScalef(1.0*aspect, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}

void goPerspective() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, 1/aspect, 0.5, 5);
glMatrixMode(GL_MODELVIEW);
}
Logged

My projects:<br />Games: Jumpman Retro-futuristic platforming iJumpman iPhone version Drumcircle PC+smartphone music toy<br />More: RUN HELLO
Tycho Brahe
Level 10
*****

λx.x


View Profile
« Reply #4 on: January 08, 2010, 10:03:38 AM »

Thanks all of you for your super-prompt responses, and for all your example code. I think I'm going to end up using msqrt's code, as its easier for me to understand, and seems to work pretty well. Again, thanks for all you're responses.

Thanks!
Logged
Pishtaco
Level 10
*****


View Profile WWW
« Reply #5 on: January 08, 2010, 11:04:04 AM »

I have a related question. How do you avoid the thing where you want to have a fullscreen resolution which is smaller than the desktop one, and when your game starts SDL first changes the resolution, and only then starts your game? It looks awfully messy.
Logged

powly
Level 4
****



View Profile WWW
« Reply #6 on: January 08, 2010, 05:23:48 PM »

For me that same code works, the screen blinks black as it searches the correct resolution, then it shows a little lighter black while stuff is initializing and then the program starts - I never get to see the resized desktop. This might depend on the SDL implementation of the operating system (I'm using xp home)
Logged
mcc
Level 10
*****


glitch


View Profile WWW
« Reply #7 on: January 08, 2010, 08:18:15 PM »

I have a related question. How do you avoid the thing where you want to have a fullscreen resolution which is smaller than the desktop one, and when your game starts SDL first changes the resolution, and only then starts your game? It looks awfully messy.
I'm not sure I get the question, but if you select 0,0 as your width and height it will just use the current screen resolution for the window size.

Maybe what you could try is creating a fullscreen window with size 0,0 (filling the screen with black, one assumes), THEN replacing it with a fullscreen window of whatever screen resolution you actually want? I'm not sure what that would do in practice.
Logged

My projects:<br />Games: Jumpman Retro-futuristic platforming iJumpman iPhone version Drumcircle PC+smartphone music toy<br />More: RUN HELLO
LemonScented
Level 7
**



View Profile
« Reply #8 on: January 09, 2010, 07:15:53 AM »

I get the question, but I don't have an answer - in fact I have the same problem and would love to know how to fix it.

Basically, my monitor is running at a nice shiny 1280*1024, but my game runs at 800*600. When I start the game fullscreen, for a few seconds before the game actually appears onscreen I see Windows, but with the resolution set to 800*600, which is really ugly for those few seconds. I think this is what Pashtaco is talking about. Worse still, for me, my computer often boots up (or wakes up after Sleep or Hibernate - stupid Vista and its bajillion ways to shut down!) in 800*600 mode if I have previously been running fullscreen SDL stuff (Passage does that to me as well if it's been run fullscreen, which is particularly awkward).
Logged

Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #9 on: January 09, 2010, 09:26:09 AM »

I have a related question. How do you avoid the thing where you want to have a fullscreen resolution which is smaller than the desktop one, and when your game starts SDL first changes the resolution, and only then starts your game? It looks awfully messy.

I don't use SDL, but I do full-screen apps across Mac OS X, Windows, and Linux using the native APIs.

I don't recall ever having this problem with my code, and you neglected to mention what operating system you were using, so I'll assume Windows (I hate doing that).

Code:
void MainWindow::CreateFullscreen(DEVMODE mode) throw ()
{
    HWND window = CreateWindowEx(0, class_name.c_str(), ASBase::System::project_name.c_str(),
                                 WS_POPUP,
                                 0, 0, mode.dmPelsWidth, mode.dmPelsHeight,
                                 HWND_DESKTOP, NULL, GetModuleHandle(NULL), NULL);

    mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
    ChangeDisplaySettings(&mode, CDS_FULLSCREEN);
    ShowCursor(false);

    ShowWindow(window, SW_SHOW);
    data->fullscreen = true;
}

I don't know how much control over this stuff you have in SDL, but this procedure works fine.  Create the window at the fullscreen size, but invisible.  Switch display modes, then show the window.  At the time of window creation (NOT window showing) the OpenGL surface is created and cleared to black (not shown here).  This way, once the window gets shown, you already have something to draw.

I'd wager that your initial window simply has nothing to draw for the first few frames, so the background desktop is showing through.  If this isn't the case, then the only suggestion I can make is to dump SDL and learn to do this for real, so you have more control over the process.
Logged



What would John Carmack do?
mcc
Level 10
*****


glitch


View Profile WWW
« Reply #10 on: January 09, 2010, 11:44:51 AM »

Average Software, do you know if it is possible to use Windows to initialize the base window while still getting to use things like SDL input and SDL_GL_SwapBuffers? Like making an SDL_SURFACE inside an existing window or something.
Logged

My projects:<br />Games: Jumpman Retro-futuristic platforming iJumpman iPhone version Drumcircle PC+smartphone music toy<br />More: RUN HELLO
Pishtaco
Level 10
*****


View Profile WWW
« Reply #11 on: January 09, 2010, 11:50:17 AM »

Yes, that's what I meant, and it's on windows. Thanks very much for the replies.
Logged

Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #12 on: January 09, 2010, 04:46:19 PM »

Average Software, do you know if it is possible to use Windows to initialize the base window while still getting to use things like SDL input and SDL_GL_SwapBuffers? Like making an SDL_SURFACE inside an existing window or something.

I literally know nothing about SDL, I don't like or use those sorts of wrapper libraries, so I can't tell you for certain.

If SDL gives some way of obtaining the HWND for the surface, then I don't see why you couldn't do it.  Or if it allows you to supply it with the window you want the surface attached to, that would work too.

You'd have to check the SDL docs and see if it has a functions dealing with HWNDs.  I would expect corresponding functions that take NSWindow* for Mac, and some kind of X-Windows reference on the Linux side.
Logged



What would John Carmack do?
Ivan
Owl Country
Level 10
*


alright, let's see what we can see


View Profile
« Reply #13 on: January 09, 2010, 05:52:35 PM »

Average Software, do you know if it is possible to use Windows to initialize the base window while still getting to use things like SDL input and SDL_GL_SwapBuffers? Like making an SDL_SURFACE inside an existing window or something.

I literally know nothing about SDL, I don't like or use those sorts of wrapper libraries, so I can't tell you for certain.

If SDL gives some way of obtaining the HWND for the surface, then I don't see why you couldn't do it.  Or if it allows you to supply it with the window you want the surface attached to, that would work too.

You'd have to check the SDL docs and see if it has a functions dealing with HWNDs.  I would expect corresponding functions that take NSWindow* for Mac, and some kind of X-Windows reference on the Linux side.

Yeah there's a way to do it. Look at SDL_GetWMInfo
Logged

http://polycode.org/ - Free, cross-platform, open-source engine.
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic