Come disegnare immagini 2D usando OpenGL, in SDL?


8

Dopo tutto, sono riuscito a trovare un semplice pezzo di codice che mostra come disegnare un'immagine 2D con 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;
    }

Sono inesperto in 2D e circa una settimana fa ha iniziato a fare scherzi con SDL. Costruivo alcune strutture semplici per avere immagini, che sarebbero su livelli, in modo che potessi avere il mio ordine di disegno, quindi gli sprite sarebbero stati disegnati dopo lo sfondo, ecc., E poi avrebbero fatto un piccolo "motore di sprite". Ho avuto uno sprite Megaman che camminava a destra e a sinistra proprio come lo volevo, sopra una semplice immagine di sfondo di 900x900.

Il fatto è che la CPU ha quasi raggiunto il 20% sul mio i5 ... quindi ho pensato di usare la scheda grafica per fare il disegno! Ho abitato in OpenGL e oggi sono finalmente riuscito a far funzionare gl3w!

Quindi ora sto cercando un modo semplice per visualizzare i miei sprite / immagini, sulla finestra, usando OpenGL. Ho provato tutti i tipi di codice che ho incontrato, ma non riesco a visualizzare nulla, nonostante abbia fatto controlli di errore praticamente ovunque, e tutto sembra funzionare correttamente!

TL: DR; Stavo cercando un semplice codice di lavoro, usando SDL, su come disegnare immagini 2D (che, se non funziona, sicuramente ho qualcosa di sbagliato).

Grazie!


1
stai usando le funzioni bitblit integrate o stai disegnando sprite da solo? può fare una differenza enorme!
Ali1S232,

Sto solo usando SDL_Blit (), nel gioco la cui performance è stata orribile
GigaBass

In realtà potresti chiarire cosa intendi? Cosa sta disegnando gli sprite da solo?
GigaBass

impostazione dei pixel nel buffer
Ali1S232

In tal caso, no, sto usando i soli BLITS forniti direttamente da SDL.
GigaBass

Risposte:


7

Ti consiglio di caricare i tuoi sprite usando il SUOLO e di renderli semplicemente disegnando quad strutturati. Se lo fai senza alcuna funzionalità obsoleta (usa shader) scoprirai che è molto veloce.


Ho dato una rapida occhiata alla biblioteca, e suona bene. Potresti forse fornire un codice di esempio molto piccolo sull'uso del SUOLO, un esempio che fornisce un'immagine semplice sarebbe fantastico! Grazie
GigaBass il

ci sono frammenti di codice sul collegamento per caricare l'immagine in. Come si esegue il rendering che dipenderà da voi, ma se si vuole fare il "modo giusto", si vorranno seguire qualcosa di simile a questo . Sfortunatamente configurare OpenGL con shader ecc. Non è così semplice e veloce, ma probabilmente ne vale la pena, soprattutto se avrai molti sprite contemporaneamente.
Eric B,

3

Ecco un punto di partenza piuttosto semplice ma ottimo per disegnare quads strutturati in OpenGL, da questo punto di partenza della funzione ho altre 7 funzioni che offrono funzionalità leggermente diverse, al disegno con colori colorati, al disegno di oggetti con valori alfa diversi e quindi abbiamo rotazione, ritaglio ecc. ecc. Ma questo dovrebbe aiutarti a iniziare :).

Modifica: codice aggiornato;

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

L'immagine è una struttura di base contenente i dati di trama (GLuint) e quindi due numeri interi per contenere larghezza e altezza.


Ho letto che glBegin, glEnd sorta di funzioni OpenGL sono state deprecate perché sono molto più lente di quelle aggiornate, è corretto? Tuttavia, per un semplice gioco 2d, questo sarà più che sufficiente per ottenere tutti gli sprite che io abbia mai desiderato senza che la GPU abbia mai superato il 50% giusto?
GigaBass

Sì, è meglio usare glDrawArrays e inviare tutti i dati dei vertici in una volta sola. Ma suppongo che la differenza sia piuttosto marginale soprattutto quando hai a che fare solo con 4 vertici.
dan369,

Supponiamo che stavo disegnando immagini 500x500, 20 di esse, ogni fotogramma, su uno schermo da 1000x1000 pixel? La differenza sarebbe notevole? Solo così ho una comprensione di quanto sia meglio
GigaBass

No, non penso che sarebbe evidente in quel caso. Ricorda che non dovresti preoccuparti troppo dell'ottimizzazione fino a quando non ti imbatti in problemi. È una trappola comune.
dan369,

Sono rimasto scioccato nel vedere che stava prendendo il 20% della mia CPU e ho subito pensato che dovevo fare qualcosa per ripararlo ... su molti computer del mio amico, non poteva funzionare a velocità normale!
GigaBass

0

SDL è necessario per te? SFML è un'alternativa a SDL che utilizza OpenGL per il rendering. Potrebbe anche essere più facile per i principianti, a causa dell'API orientata agli oggetti.


downvote perché la tua risposta non sta risolvendo il suo problema. Vuole sapere come lavorare con OpenGL. Non sta usando una soluzione alternativa.
Ali1S232

Sì, volevo evitare di passare da SDL a SFML, mi piace abbastanza ... abituato al suo funzionamento. Vuoi dire che SFML può fare il semplice disegno che SDL può fare con i blits, usando OpenGL per il rendering? Sarebbe davvero molto buono.
GigaBass

2
@ user1896797: Sì SFML utilizza OpenGL per tutte le cose grafiche.
szotp,

È fantastico se è come dici tu, ci proverò! Voterei se potessi!
GigaBass

Confermato, utilizza OpenGL. Non posso accettare il tuo però, solo perché la risposta deve riguardare la domanda. Ma un grande grazie!
GigaBass,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.