Sign in to follow this  
Silent Dragon

SDL / OpenGL

Recommended Posts

I was looking through this tutorial http://gpwiki.org/index.php/C:SDL_OGL and the source code that goes with it, and i was just wondering what the differece is between the first source code file and the second. Is the second one faster? Or better? I was also wondering which is faster (in order) SDL, the first SDL/OGL method or the second SDL/OGL method? Any help would be greatly appreciated Al

Share this post


Link to post
Share on other sites
The difference is that the first one uses SDL's drawing routines with OpenGL (via the SDL_OPENGLBLIT parameter). This is "deprecated and not recommended for new code" according to the SDL Documentation.

The second example uses OpenGL for rendering with glBegin et al. This is definately the reccommended approach. For some reason, this example also passes SDL_OPENGLBLIT to SDL_SetVideoMode. You should replace this with just SDL_OPENGL.

This second method *should* also be faster because it will use your graphics card's 3D acceleration, though mileage may vary.

Hope that helps.

Share this post


Link to post
Share on other sites
Hmm I got it working...partly. I got it to work with the image they specified (which wasa square) but when I try and make it general it doesnt display the picture on the surface, all i get is a white shape thats the size of the image.

Sprite class definition

class Sprite
{
public:
Sprite(char *Filename);
~Sprite() { SDL_FreeSurface(m_sprite); }

void Draw(SDL_Surface *dest);

void SetX(int x) { m_x = x; }
void SetY(int y) { m_y = y; }

int GetH() { return m_h; }
int GetW() { return m_w; }
int GetY() { return m_y; }
int GetX() { return m_x; }

private:
SDL_Surface* m_sprite;

GLuint image; //This is our texture
SDL_Surface *temp; //This surface will be used to load data into our texture declared above

int m_x;
int m_y;
int m_w;
int m_h;
};




Sprite class code

Sprite::Sprite(char* Filename)
{
m_sprite = SDL_LoadBMP(Filename);
temp = SDL_LoadBMP(Filename);

m_w = m_sprite->w;
m_h = m_sprite->h;
m_x = 0;
m_y = 0;



}

void Sprite::Draw(SDL_Surface *dest)
{
//Create the texture
glGenTextures(1, &image);

//Load the texture
glBindTexture(GL_TEXTURE_2D, image);

//Generate the texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, temp->w, temp->h, 0, GL_BGR, GL_UNSIGNED_BYTE, temp->pixels);

//Use linear filtering, very good
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);



//Enable texturing
glEnable(GL_TEXTURE_2D);

//Load the texture
glBindTexture(GL_TEXTURE_2D, image);

glBegin(GL_QUADS);
//Top-left vertex (corner)
glTexCoord2f(0,0);
glVertex3f((float)m_x, (float)m_y, 0.0f);

//Bottom-left vertex (corner)
glTexCoord2f(1,0);
glVertex3f((float)(m_x + m_w), (float)m_y, 0.0f);

//Bottom-right vertex (corner)
glTexCoord2f(1,1);
glVertex3f((float)(m_x + m_w), (float)(m_y + m_h), 0.0f);

//Top-right vertex (corner)
glTexCoord2f(0,1);
glVertex3f((float)m_x, (float)(m_y + m_h), 0.0f);
glEnd();

//Disable texturing
glDisable(GL_TEXTURE_2D);
// FastBlit(m_sprite, dest, m_x, m_y);
}




And the main code to call it


Sprite Ball("Ball.bmp");

//Make certain everything is cleared from the screen before we draw to it
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Ball.Draw(screen);
//Flush the OpenGL pipeline
glFlush();
//SDL_Flip(screen);
SDL_GL_SwapBuffers();





Not quite sure why it doesnt work properly, but if you need more code then i can supply it. Thanks for any help in pointing me in the right direction

[Edited by - Silent Dragon on May 1, 2006 10:49:34 AM]

Share this post


Link to post
Share on other sites
Everything before glEnable() in your Sprite::Draw() should be called once, not every frame. Preferably in an init() method.

The white rect means the texture data isn't being uploaded (check the return codes).

Share this post


Link to post
Share on other sites
Quote:
Original post by Boder
Everything before glEnable() in your Sprite::Draw() should be called once, not every frame. Preferably in an init() method.

The white rect means the texture data isn't being uploaded (check the return codes).


OK well, if I move it to the constructor of the class then nothing loads crrectly. You can see in the image posted above that blue thing shows, if the code before glEnable() is put in the constructor, and therefore only run once, the space where the blue image would be is just a white space too. Which return values should i be checking? Thanks for your help.

Share this post


Link to post
Share on other sites
It may or may not be the issue, but it's worth noting that textures must have dimensions that are powers of two. (eg. 8, 16, 32, 64, etc)

Share this post


Link to post
Share on other sites
Quote:
Original post by HopeDagger
It may or may not be the issue, but it's worth noting that textures must have dimensions that are powers of two. (eg. 8, 16, 32, 64, etc)


Thats probably my problem. How would I attempt to load a bmp file that isn't with those dimentions as a texture? Or should I just redo the bmp files and makesure they are all the correct sizes?

EDIT:- That IS the problem, I didn't know about the texture size restrictions, thanks :) Just hope there is a way to stretch a bmp onto a texture of a certain size.

Share this post


Link to post
Share on other sites
Call glGetError() after each OpenGL function to detect errors. If you get a GL_INVALID_VALUE error after calling glTexImage2D() then non-POT image is the likely culprit. Either store the sprite on a POT surface and adjust the texture coordinates, or resize the sprite to POT.

There isn't a need to call glBindTextures() twice in Sprite::Draw(). OpenGL works like a state machine, once you bind a texture, it stays binded until you change it.

Also there isn't any need to keep the SDL_Surface around once it has been sent to Opengl through glTexImage2D().

Here is a small checklist I use when start GL projects:
Set glColor4f() to all white(1,1,1,1)
Disable GL_LIGHTING
Disable GL_DEPTH_TEST
Double-check texture coordinates
Check matrix mode properly setup

Sprite constructor should look something like this.

Sprite::Sprite(char* Filename)
{
m_sprite = SDL_LoadBMP(Filename);
if(NULL == m_sprite)return;//ERROR CHECKING IS VERY IMPORTANT

//Create the texture
glGenTextures(1, &image);

//Load the texture
glBindTexture(GL_TEXTURE_2D, image);

//It's a good ideal to call SDL_LockSurface() before
//using the SDL_Surface 'pixel' field.
...
//It's a good ideal to make sure surface is
//actually a 24bit BGR formatted surface before calling glTextImage2D()
...
//Generate the texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, sprite->w, sprite->h, 0, GL_BGR, GL_UNSIGNED_BYTE, sprite->pixels);

//You might want to check out the texture env options and set them here.Example:
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

//Use linear filtering, very good
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
m_w = m_sprite->w;
m_h = m_sprite->h;
m_x = 0;
m_y = 0;
//unlocksurface and free
...
SDL_FreeSurface(m_sprite);//NO LONGER ANY NEED FOR THIS SURFACE
}
void Sprite::Draw(SDL_Surface *dest)
{
Do gl enable stuff and drawing here
}




Good Luck and hope you get things working.[Edit - Took too long, looks like you solved:)]

Share this post


Link to post
Share on other sites
Quote:
Original post by Jack Sotac
Call glGetError() after each OpenGL function to detect errors. If you get a GL_INVALID_VALUE error after calling glTexImage2D() then non-POT image is the likely culprit. Either store the sprite on a POT surface and adjust the texture coordinates, or resize the sprite to POT.

There isn't a need to call glBindTextures() twice in Sprite::Draw(). OpenGL works like a state machine, once you bind a texture, it stays binded until you change it.

Also there isn't any need to keep the SDL_Surface around once it has been sent to Opengl through glTexImage2D().

Here is a small checklist I use when start GL projects:
Set glColor4f() to all white(1,1,1,1)
Disable GL_LIGHTING
Disable GL_DEPTH_TEST
Double-check texture coordinates
Check matrix mode properly setup

Sprite constructor should look something like this.
*** Source Snippet Removed ***
Good Luck and hope you get things working.[Edit - Took too long, looks like you solved:)]


Thanks :p that tidied it up a little, and I added in the locking and unlocking. Just not sure how to put make a texture out of any sized bmp, if its possible..

Share this post


Link to post
Share on other sites
You can either create a new SDL surface that is 2^x and scale the image you load up to the next 2^x or you can just blit the image into one corner and use texture coordinates to blit the specified part of the texture.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this