Bagaimana cara menggambar gambar 2D menggunakan OpenGL, di SDL?

8

Setelah semuanya, saya berhasil menemukan sepotong kode sederhana yang menunjukkan cara menggambar gambar 2D dengan 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;
    }

Saya tidak berpengalaman dalam 2D, dan sekitar seminggu yang lalu mulai mengacaukan SDL. Membangun beberapa struktur sederhana untuk memiliki gambar, yang akan berlapis-lapis, sehingga saya dapat memiliki urutan gambar saya sendiri, sehingga sprite akan diambil setelah latar belakang, dll, dan kemudian melakukan sedikit "mesin sprite". Saya mendapatkan sprite Megaman yang berjalan kiri dan kanan seperti yang saya inginkan, di atas gambar latar 900x900an sederhana.

Masalahnya, CPU hampir mencapai 20% pada i5 saya ... jadi saya berpikir untuk menggunakan kartu grafis untuk menggambar! Digabungkan abit ke OpenGL dan hari ini, akhirnya berhasil membuat gl3w bekerja!

Jadi sekarang saya sedang mencari cara sederhana untuk menampilkan sprite / gambar saya, di jendela, melalui penggunaan OpenGL. Saya sudah mencoba semua jenis kode yang saya temui, tetapi saya tidak bisa menampilkan apa pun, meskipun saya telah melakukan pemeriksaan kesalahan pada dasarnya di mana-mana, dan semuanya tampak benar!

TL: DR; Saya sedang mencari beberapa kode kerja sederhana, menggunakan SDL, tentang cara menggambar gambar 2D (yang, jika tidak berfungsi, pasti saya punya sesuatu yang salah).

Terima kasih!

GigaBass
sumber
1
apakah Anda menggunakan fungsi bitblit bawaan atau Anda menggambar sprite sendiri? itu bisa membuat perbedaan besar!
Ali1S232
Saya hanya menggunakan SDL_Blit (), pada game yang kinerjanya buruk
GigaBass
Sebenarnya bisakah Anda menjelaskan apa yang Anda maksud? Apa menggambar sprite sendiri?
GigaBass
pengaturan piksel dalam buffer
Ali1S232
Dalam hal itu, tidak, saya hanya menggunakan BLITS yang disediakan oleh SDL secara langsung.
GigaBass

Jawaban:

7

Saya sarankan memuat sprite Anda menggunakan SOIL , dan kemudian merendernya dengan hanya menggambar paha depan bertekstur. Jika Anda melakukannya tanpa fungsionalitas usang (gunakan shader), Anda akan menemukannya sangat cepat.

Eric B
sumber
Aku melihat sekilas ke perpustakaan, dan itu terdengar bagus. Bisakah Anda memberikan contoh kode yang sangat kecil tentang penggunaan SOIL, sebuah contoh yang menghasilkan gambar sederhana akan lebih bagus! Terima kasih
GigaBass
ada potongan kode pada tautan untuk memuat gambar. Cara Anda merendernya akan tergantung pada Anda, tetapi jika Anda ingin melakukannya dengan "cara yang benar", Anda akan ingin mengikuti sesuatu seperti ini . Sayangnya pengaturan OpenGL dengan shader dll tidak begitu cepat dan mudah tetapi mungkin sepadan, terutama jika Anda akan memiliki banyak sprite sekaligus.
Eric B
3

Berikut ini adalah titik awal yang agak dasar tetapi bagus untuk menggambar paha depan bertekstur di OpenGL, dari titik awal fungsi ini saya memiliki 7 fungsi lain yang menyediakan fungsionalitas yang sedikit berbeda, untuk menggambar dengan warna gelap, untuk menggambar item dengan nilai alpha yang berbeda dan kemudian kami memiliki rotasi, kliping dll. Tapi ini akan membantu Anda memulai :).

Edit: Kode Diperbarui;

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

Gambar adalah struktur dasar yang memegang data tekstur (GLuint) dan kemudian dua bilangan bulat untuk menahan lebar & tinggi.

dan369
sumber
Saya telah membaca sekitar bahwa glBegin, glEnd semacam fungsi OpenGL telah ditinggalkan karena mereka jauh lebih lambat daripada yang terbaru, apakah ini benar? Namun, untuk gim 2d sederhana, ini akan lebih dari cukup untuk mendapatkan semua sprite yang saya inginkan tanpa gpu melebihi 50% kan?
GigaBass
Yap, lebih baik menggunakan glDrawArrays dan mengirim semua data vertex dalam sekali jalan. Tapi saya kira perbedaannya agak marjinal terutama ketika Anda hanya berurusan dengan 4 simpul.
dan369
Katakanlah saya sedang menggambar 500x500 gambar, 20 di antaranya, setiap frame, ke layar 1000x1000 piksel? Apakah perbedaannya akan terlihat? Asal saya tahu seberapa baik itu
GigaBass
Tidak, saya tidak berpikir itu akan terlihat dalam kasus itu. Ingat Anda tidak perlu terlalu khawatir tentang pengoptimalan sampai Anda benar-benar mengalami masalah. Ini perangkap umum.
dan369
Saya terkejut melihat bahwa itu mengambil 20% dari CPU saya dan segera berpikir saya harus melakukan sesuatu untuk memperbaikinya ... pada beberapa komputer teman saya, itu tidak dapat berjalan pada kecepatan normal!
GigaBass
0

Apakah SDL diperlukan untuk Anda? SFML adalah alternatif untuk SDL yang menggunakan OpenGL untuk rendering. Mungkin juga lebih mudah bagi pemula, karena API berorientasi objek.

szotp
sumber
downvote karena jawaban Anda tidak menyelesaikan masalahnya. Dia ingin tahu cara bekerja dengan OpenGL. Dia tidak menggunakan solusi alternatif.
Ali1S232
Ya, saya agak ingin menghindari pindah dari SDL ke SFML, saya sangat menyukainya ... terbiasa dengan kerjanya. Apakah maksud Anda SFML dapat melakukan menggambar mudah yang dapat dilakukan SDL dengan blits, menggunakan OpenGL untuk rendering? Itu sebenarnya sangat bagus.
GigaBass
2
@ user1896797: Ya SFML menggunakan OpenGL untuk semua hal grafis.
szotp
Itu bagus jika seperti yang Anda katakan, saya akan mencobanya! Akan membenarkan jika saya bisa!
GigaBass
Dikonfirmasi, memang menggunakan OpenGL. Tidak dapat menerima milikmu, hanya karena jawabannya harus berhubungan dengan pertanyaan. Tapi terima kasih banyak!
GigaBass