3
\$\begingroup\$

I'm going to create a game in C++ with SDL & openGL but adding textures won't work. the code is in some different classes. here's the main file

//==============================================================================
#include "ZOMBOX.h"

//==============================================================================
ZOMBOX::ZOMBOX() {

    isRunning = true;
}

//------------------------------------------------------------------------------
int ZOMBOX::Execute() {
    Init();

    bool mainloop = false;

    SDL_Event event;

    //Create an texture
    unsigned int Ball_texture = 0;
    //Load the image into the texture using the function
    Ball_texture = loadTexture("Smile.png");
    std::cout << "OpenGL is running\n";

    while(isRunning) {
        while(SDL_PollEvent(&event)) {
            Event(&event);
        }
        if(mainloop == false){
            std::cout << "Main loop has started\n";
            mainloop = true;
        }
        Logic();
        Render();
        }

    //Clear();

    SDL_Quit();

    return 0;
}

//==============================================================================
int main(int argc, char* argv[]) {
    ZOMBOX theApp;

    return theApp.Execute();
}

//==============================================================================

Ok, now the rendering;

//============================================================================== #include "ZOMBOX.h"

//==============================================================================
void ZOMBOX::Render() {

    extern float ballX;
    extern float ballY;
    extern float ballWH;
    extern int vellX;
    extern int vellY;
    extern unsigned int Ball_texture;
    Ball_texture = loadTexture("Smile.png");

    //RENDERING to the screen
    //Enable textures when we are going to blend an texture
    glClear(GL_COLOR_BUFFER_BIT);
    glPushMatrix(); //Start rendering phase
    glOrtho(0,800,600,0,-1,1); //Set the matrix
    glColor4ub(0,0,0,255); //White color
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, Ball_texture);

    glBegin(GL_QUADS); //Start drawing the pad
    //We set the corners of the texture using glTexCoord2d
    glTexCoord2d(0,0); glVertex2f(ballX,ballY); //Upper-left corner
    glTexCoord2d(1,0); glVertex2f(ballX+ballWH,ballY); //Upper-right corner
    glTexCoord2d(1,1); glVertex2f(ballX+ballWH,ballY+ballWH); //Down-right corner
    glTexCoord2d(0,1); glVertex2f(ballX,ballY+ballWH); //Down-left corner
    glEnd(); //End drawing
    //Disable textures when we are done using them
    glDisable(GL_TEXTURE_2D);

    glPopMatrix(); //End rendering phase
    SDL_GL_SwapBuffers();

    SDL_Delay(1);
}

//==============================================================================

i know the comments are not right but i understand it...

now the texture; here's the fault i think

//==============================================================================
#include "ZOMBOX.h"
//==============================================================================
//Function for loading an image into an texture
GLuint ZOMBOX::loadTexture( const std::string &fileName )
{
    SDL_Surface* image = IMG_Load( fileName.c_str() );

    SDL_DisplayFormatAlpha(image);

    unsigned object(0);

    glGenTextures(1, &object);

    glBindTexture(GL_TEXTURE_2D, object);

    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);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);

    //Free surface
    SDL_FreeSurface(image);

return object;
}
//==============================================================================

I use variables you cant see but that's no problem thus they are not nessecary(i think).

Sorry for my bad English im just a dutch highschool student.

\$\endgroup\$

3 Answers 3

5
\$\begingroup\$

In addition to the comments above, your conversion of an SDL_Surface to an OpenGL texture is incorrect. You're missing two important issues:

  1. Ensure that the image dimensions are a power of two. (64, 128, 256, 512, etc)
  2. Ensure that your SDL_Surface is in the pixel format that you're telling OpenGL that it's using (GL_RGBA, GL_UNSIGNED_BYTE, in your case). This one could easily be the cause of crashes, if your image isn't actually stored as a 32-bit image.
  3. I also tell OpenGL to automatically generate mipmaps. No need to do that part, but I've included it here for completeness.

Here's the code I use for doing this texture setup. Basic idea: create a new SDL_Surface of the correct size and pixel format, copy the original surface into it, create the OpenGL texture from the correctly-formatted copy, and then clean up.

Source code:

static int power_of_two(int input)
{
    int value = 1;

    while ( value < input ) {
        value <<= 1;
    }
    return value;
}

int ConvertSDLSurfaceToTexture( SDL_Surface *source )
{
    SDL_Rect    area;
    uint32_t saved_flags;
    uint8_t  saved_alpha;

    SDL_SetAlpha(source, 0, SDL_ALPHA_OPAQUE);

    m_width = (float)source->w;
    m_height = (float)source->h;

    int w = power_of_two(source->w);
    int h = power_of_two(source->h);

    SDL_Surface *image = SDL_CreateRGBSurface(
                                          SDL_SWSURFACE,
                                          w, h,
                                          32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
                                          0x000000FF,
                                          0x0000FF00,
                                          0x00FF0000,
                                          0xFF000000
#else
                                          0xFF000000,
                                          0x00FF0000,
                                          0x0000FF00,
                                          0x000000FF
#endif
                                          );
    assert(image != NULL);

    saved_flags = source->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
    saved_alpha = source->format->alpha;
    if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
        SDL_SetAlpha(source, 0, 0);
    }

    /* Copy the surface into the GL texture image */
    area.x = 0;
    area.y = 0;
    area.w = source->w;
    area.h = source->h;
    SDL_BlitSurface(source, &area, image, &area);

    /* Restore the alpha blending attributes */
    if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
        SDL_SetAlpha(source, saved_flags, saved_alpha);
    }

    /* Create an OpenGL texture for the image */
    GLuint t;
    glGenTextures(1, &t);

    glBindTexture(GL_TEXTURE_2D, m_texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
    glTexImage2D(GL_TEXTURE_2D,
                 0,
                 GL_RGBA,
                 w, h,
                 0,
                 GL_RGBA,
                 GL_UNSIGNED_INT_8_8_8_8_REV,
                 image->pixels);

    SDL_FreeSurface(image); /* done with this copy of the input surface */

    return t;
}
\$\endgroup\$
6
  • \$\begingroup\$ @ Trevor Powell i made my image with Paint.net,added an alpha layer and saved it as a 32-bit .png file. i use this as an function which i got from my friend he explained me what it does and i understood it, but he made a big main.cpp file, and i use different files for different functions, like render.cpp loadTexture.cpp ZOMBOX.cpp(which is the main file) maybe that makes a difference, one question, how should i use your code? \$\endgroup\$ Mar 1, 2012 at 13:08
  • \$\begingroup\$ can i use it like so: GLuint ZOMBOX::loadTexture(){yourfunction} or should it look like this: GLuint ZOMBOX::loadTexture(){myfunction yourfunction} ? i don't know how to implement your source code. please explain. Still THNX! \$\endgroup\$ Mar 1, 2012 at 13:27
  • \$\begingroup\$ You'd do IMG_Load(), then my function using the SDL_Surface that was created to create the OpenGL texture, then SDL_FreeSurface() to destroy the SDL_Surface you loaded. \$\endgroup\$ Mar 2, 2012 at 9:48
  • \$\begingroup\$ I will try that i'v been trying to use your function but my compiler(Mingw) keeps telling me that it cant recognize Uint32 & uint8 what's the problem then. I'm not really familiar with C++ most of time i use C \$\endgroup\$ Mar 2, 2012 at 11:20
  • 1
    \$\begingroup\$ uint32 & uint8 must be uint32_t & uint8_t. \$\endgroup\$ Mar 3, 2012 at 19:37
2
\$\begingroup\$

Are there any errors when loading the image? Try to verify that the image loads properly.

After this:

SDL_Surface* image = IMG_Load( fileName.c_str() );

Add this:

if(!image) {
    printf("IMG_Load: %s\n", IMG_GetError());
    // handle error
}
\$\endgroup\$
1
  • \$\begingroup\$ i tried that but it gives no error until i delete my image file. some weird sort of smiley. i see what i can do with your answer. thnx \$\endgroup\$ Mar 1, 2012 at 12:57
1
\$\begingroup\$

You load the texture every time you Render().
It should be this way:

  1. You start the program
  2. Load the texture (before the while-loop)
  3. Render the texture (in the while-loop)
  4. Unload the texture (after the while-loop)
  5. Close the program
\$\endgroup\$
1
  • \$\begingroup\$ Hmm mayby that's a problem. I load the texture twice. one time before the while loop, and in the rendering part... I will thange that and see what it does. \$\endgroup\$ Mar 1, 2012 at 13:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .