PDA

View Full Version : Drawing textures from an SDL_Surface: BMP image > Surface > Texture > Quad



amorag59
11-28-2014, 02:02 PM
Hello,

I am trying to draw a 2D bitmap image to the screen (or defined space on the window) in Opengl context. I am using the SDL and SDL_Image libraries. I'm getting an unhandled win32 exception when I run the code posted below. I think I also need to draw the quad where the texture will go on the screen (buffer), but have not done that. The program didn't return this error when I had GL_BITMAP in glTexImage2D instead of BL_UNSIGNED_BYTE, but in that situation the window was blank. What am I doing wrong in this code?





/* Draw */




SDL_Surface *surface;
char *image_path = "helloworld.bmp";
int x_pos = 720;
int y_pos = 450;

GLuint mTextureWidth = 720;
GLuint mTextureHeight = 450;

SDL_Surface *image = IMG_Load ( image_path );
if ( !image )
{
std::cout << "Error Cannot load image";
}
// Draws the image on the surface:
SDL_Rect rcDest = { x_pos, y_pos, 0, 0 };
SDL_BlitSurface ( image, NULL, surface, &rcDest );
// something like SDL_UpdateRect(surface, x_pos, y_pos, image->w, image->h); is missing here

SDL_FreeSurface ( image );

glEnable(GL_TEXTURE_2D);

GLuint textures;
glGenTextures(1, &textures); //Number of textures stored in array name specified

glBindTexture(GL_TEXTURE_2D, textures);


/* Map the surface to the texture in video memory */
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 720, 450, 0, GL_RGB, GL_UNSIGNED_BYTE, surface); //GL_BITMAP,

glBindTexture(GL_TEXTURE_2D, textures);

//Render texture quad
glBegin( GL_QUADS );
glTexCoord2f( 0.f, 0.f ); glVertex2f( 0.f, 0.f );
glTexCoord2f( 1.f, 0.f ); glVertex2f( mTextureWidth, 0.f );
glTexCoord2f( 1.f, 1.f ); glVertex2f( mTextureWidth, mTextureHeight );
glTexCoord2f( 0.f, 1.f ); glVertex2f( 0.f, mTextureHeight );
glEnd();


glDisable(GL_TEXTURE_2D);

//Do I need to create another GL_QUADS here to put the texture on the screen?




glPopMatrix(); //End rendering phase



//Draw to screen
SDL_GL_SwapBuffers();

SDL_Delay(10); //Hold rendered frame on screen for indicated amount of time

GClements
11-28-2014, 04:57 PM
SDL_Surface *surface;

You don't appear to initialise this variable.




glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 720, 450, 0, GL_RGB, GL_UNSIGNED_BYTE, surface);

The last argument to glTexImage2D() must be a pointer to the actual pixel data, e.g. surface->pixels for an SDL surface (in some cases, you may need to call SDL_LockSurface() first).

The data must be in the expected format; in this case, 450 rows of 720 pixels at 3 bytes per pixel. Unless you have changed the unpacking parameters with glPixelStorei(), there should be no padding between rows (i.e. surface->pitch must be 2160). Note that if the width wasn't a multiple of 4, you would need to call glPixelStorei(GL_UNPACK_ALIGNMENT, ...), as the default requires each row of pixel data to be aligned to a 4-byte boundary.

Textures whose width or height aren't a power of two require OpenGL 2.0 or the GL_ARB_texture_non_power_of_two extension.

amorag59
11-30-2014, 10:04 PM
I got it to work, I never thought OpenGL would be so difficult to write from scratch. I ended up looking up how each individual function works. I may create a function to simplify things or tweak the code if not set up properly. Thanks for the guidance!




glClear(GL_COLOR_BUFFER_BIT);



glPushMatrix(); //Start phase

glOrtho(0,720,480,0,-1,1); //Set the matrix





/* Draw */

char *image_path = "helloworld.bmp";
int x_pos = 124;
int y_pos = 124;

GLuint mTextureWidth = 124;
GLuint mTextureHeight = 124;

SDL_Surface *image = IMG_Load ( image_path );
if ( !image )
{
std::cout << "Error Cannot load image";
}

float x = 450.0f;
float y = 150.0f;
float width = 100.0f;
float height = 100.0f;

float iheight = 124.0f;
float iwidth = 124.0f;


glEnable(GL_TEXTURE_2D);

//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GLuint textures;
glGenTextures(1, &textures); //Number of textures stored in array name specified

glBindTexture(GL_TEXTURE_2D, textures);

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_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

// Map the surface to the texture in video memory
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 124, 124, 0, GL_RGB, GL_UNSIGNED_BYTE, image->pixels); //GL_BITMAP
SDL_FreeSurface ( image );


glBindTexture(GL_TEXTURE_2D, textures);

//Render texture quad
glBegin( GL_QUADS );
glTexCoord2f( 0.f, 0.f ); glVertex2f(x, y); //Bottom left
glTexCoord2f( 1.f, 0.f ); glVertex2f(x + iwidth, y); //Bottom right
glTexCoord2f( 1.f, 1.f ); glVertex2f(x + iwidth, y + iheight); //Top right
glTexCoord2f( 0.f, 1.f ); glVertex2f(x, y + iheight); //Top left
glEnd();

glDisable(GL_TEXTURE_2D);


glPopMatrix(); //End rendering phase