8
\$\begingroup\$

After everything, I managed to find a simple piece of code that shows how to draw a 2D image with openGL:

    #include "SDL/SDL.h"
    #include "SDL/SDL_opengl.h"
    #include "SDL/SDL_image.h"

    const int SCREEN_WIDTH = 640;
    const int SCREEN_HEIGHT = 480;
    const int SCREEN_BPP = 32;

    int tex;

    int loadTexture(char* fileName){
        SDL_Surface *image=IMG_Load(fileName);
        SDL_DisplayFormatAlpha(image);
        GLuint object;
        glGenTextures(1,&object);
        glBindTexture(GL_TEXTURE_2D,object);
        glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
        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);
        SDL_FreeSurface(image);
        return object;
    }
    void init(){
        glClearColor(0.0,0.0,0.0,0.0);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0,800,600,1.0,-1.0,1.0);
        glEnable(GL_BLEND);
        glEnable(GL_TEXTURE_2D);
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
        tex = loadTexture("hi.png");
    }
    void draw(){
        glClear(GL_COLOR_BUFFER_BIT);
        glBindTexture(GL_TEXTURE_2D,tex);
        glBegin(GL_QUADS);
            glTexCoord2f(0,0);
            glVertex2f(0,0);
            glTexCoord2f(1,0);
            glVertex2f(500,0);
            glTexCoord2f(1,1);
            glVertex2f(500,500);
            glTexCoord2f(0,1);
            glVertex2f(0,500);
        glEnd();
        glFlush();
    }
    int main(int argc,char** argv){
        SDL_Init(SDL_INIT_EVERYTHING);
        SDL_Surface* screen=SDL_SetVideoMode(800,600,32,SDL_SWSURFACE|SDL_OPENGL);
        bool running=true;
        Uint32 start;
        SDL_Event event;
        init();
        while(running){
            start=SDL_GetTicks();
            draw();
            while(SDL_PollEvent(&event)){
                switch(event.type){
                    case SDL_QUIT:
                        running=false;
                        break;
                }
            }
            SDL_GL_SwapBuffers();
            if(1000/60>(SDL_GetTicks()-start))
                SDL_Delay(1000/60-(SDL_GetTicks()-start));
        }
        SDL_Quit();
        return 0;
    }

I'm inexperienced in 2D, and about a week ago started messing with SDL. Built some simple structures to have images, which would be on layers, so I could have my own drawing order, so sprites would be drawn after background, etc, and then did a little "sprite engine". I got a Megaman sprite walking left and right just like I wanted it, above a simple 900x900ish background image.

Thing is, CPU almost reached 20% on my i5... so I thought of using the graphic card to do the drawing! Delved abit into OpenGL and today, finally managed to get gl3w working!

So now I'm looking for a simple way to display my sprites/images, on the window, through use of OpenGL. I've tried all sorts of code I ran across, but I can't get anything displaying, despite that I've done error checks basically everywhere, and everything seems to check out to be right!

TL:DR; I was looking for some simple working code, using SDL, on how to draw 2D images (which, if it doesn't work, for sure I've got something wrong).

Thanks!

\$\endgroup\$
6
  • 1
    \$\begingroup\$ are you using built-in bitblit functions or are you drawing sprites on your own? it can make a huge difference! \$\endgroup\$
    – Ali1S232
    Commented Jan 2, 2013 at 18:29
  • \$\begingroup\$ I am just using SDL_Blit(), on the game which's performance was awful \$\endgroup\$
    – parreirat
    Commented Jan 2, 2013 at 18:49
  • \$\begingroup\$ Actually could you clarify what you mean? What is drawing sprites on my own? \$\endgroup\$
    – parreirat
    Commented Jan 2, 2013 at 18:57
  • \$\begingroup\$ setting pixels in the buffer \$\endgroup\$
    – Ali1S232
    Commented Jan 3, 2013 at 4:54
  • \$\begingroup\$ In that case, no, am using the only the BLITS provided by SDL directly. \$\endgroup\$
    – parreirat
    Commented Jan 3, 2013 at 16:41

4 Answers 4

7
\$\begingroup\$

I recommend loading your sprites using SOIL, and then rendering them by just drawing textured quads. If you do it without any deprecated functionality (use shaders) you will find it's very fast.

\$\endgroup\$
2
  • \$\begingroup\$ I took a quick look at the library, and that does sound good. Could you possibly provide a very small example code on using SOIL, an example outputting a simple image would be great! Thanks \$\endgroup\$
    – parreirat
    Commented Jan 2, 2013 at 18:56
  • \$\begingroup\$ there are code snippets on the link for loading the image in. How you render it will depend on you, but if you want to do it the "right way", you will want to follow something like this. Unfortunately setting up OpenGL with shaders etc. is not so quick and easy but probably worth it, especially if you will have a lot of sprites at once. \$\endgroup\$
    – Eric B
    Commented Jan 2, 2013 at 19:01
3
\$\begingroup\$

Here's a rather basic but great starting point to drawing textured quads in OpenGL, from this function starting point I have 7 other functions that provide slightly different functionality, to drawing with tinted colours, to drawing items with different alpha values and then we have rotation, clipping etc. etc. But this should help get you started :).

Edit: Updated Code;

void Draw(int x, int y, Image* texture, bool blendFlag) {
//Bind Texture
glBindTexture(GL_TEXTURE_2D, texture->getData());

if (blendFlag)
{
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

GLfloat Vertices[] = {(float)x, (float)y, 0,
                    (float)x + texture->getWidth(), (float)y, 0,
                    (float)x + (float)texture->getWidth(), (float)y + (float)texture->getHeight(), 0,
                    (float)x, (float)y + (float)texture->getHeight(), 0};
GLfloat TexCoord[] = {0, 0,
    1, 0,
    1, 1,
    0, 1,
};
GLubyte indices[] = {0,1,2, // first triangle (bottom left - top left - top right)
                     0,2,3}; // second triangle (bottom left - top right - bottom right)

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, Vertices);

glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, TexCoord);

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);

glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

if (blendFlag) glDisable(GL_BLEND);
}

Image is a basic structure holding the texture data (GLuint) and then two integers to hold width & height.

\$\endgroup\$
5
  • \$\begingroup\$ I've been reading around though that glBegin, glEnd sort of OpenGL functions have been deprecated because they are muuuch slower than the up-to-date ones, is this correct? Still, for a simple 2d game, this will be more than enough to get all the sprites I ever want without the gpu ever exceeding 50% right? \$\endgroup\$
    – parreirat
    Commented Jan 3, 2013 at 16:46
  • \$\begingroup\$ Yep, its better to use glDrawArrays and sending all the vertex data in one go. But i suppose the difference is rather marginal especially when your only dealing with 4 vertices. \$\endgroup\$
    – dan369
    Commented Jan 3, 2013 at 17:19
  • \$\begingroup\$ Say I was drawing 500x500 images, 20 of them, every frame, onto a 1000x1000 pixel screen? Would the difference be notable? Just so I have a grasp of how much better it is \$\endgroup\$
    – parreirat
    Commented Jan 3, 2013 at 18:42
  • \$\begingroup\$ No I don't think it would be noticeable in that case. Remember you shouldn't worry too much about optimisation until you actually run into issues. Its a common pitfall. \$\endgroup\$
    – dan369
    Commented Jan 4, 2013 at 3:08
  • \$\begingroup\$ I was shocked to see that it was taking 20% of my CPU and immediately thought I had to do something to fix it... on several of my friend's computers, it couldn't run at normal speed! \$\endgroup\$
    – parreirat
    Commented Jan 4, 2013 at 13:00
0
\$\begingroup\$

Is SDL necessary for you? SFML is alternative to SDL that uses OpenGL for rendering. It may be also easier for beginners, because of the object-oriented API.

\$\endgroup\$
6
  • \$\begingroup\$ downvote because your answer is not solving his problem. He wants to know how to work with OpenGL. He is not using for an alternative solution. \$\endgroup\$
    – Ali1S232
    Commented Jan 2, 2013 at 18:28
  • \$\begingroup\$ Yeah, I kinda wanted to avoid moving from SDL to SFML, I like it quite abit... used to it's workings. Do you mean SFML can do the easy drawing SDL can do with blits, using OpenGL for rendering? That would actually be very good. \$\endgroup\$
    – parreirat
    Commented Jan 2, 2013 at 18:51
  • 2
    \$\begingroup\$ @user1896797: Yes SFML uses OpenGL for all the graphical stuff. \$\endgroup\$
    – szotp
    Commented Jan 2, 2013 at 19:14
  • \$\begingroup\$ That's great if it's as you say, I'll give it a spin! Would upvote if I could! \$\endgroup\$
    – parreirat
    Commented Jan 2, 2013 at 20:44
  • \$\begingroup\$ Confirmed, does indeed use OpenGL. Can't accept yours though, just because of the answer having to relate to question. But a big thank you! \$\endgroup\$
    – parreirat
    Commented Jan 2, 2013 at 20:57
0
\$\begingroup\$

The CPU is working the most time on the bucle that wait to the Next frame. You must use a invalidate rect o know that you can do much more without use more CPU

\$\endgroup\$

You must log in to answer this question.

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