Jumat, 22 Mei 2015

Tekstur untuk Objek 2D

Belum mau berhenti nge-blog, tapi ini artilel terakhir hari ini, besok lanjut lagi yah...

Salam Sukses selalu rekan-rekan sekalian...

Berikut ini aku akan memperkenalkan kepada rekan-rekan tekstur yang sangat bermanfaat untuk membuat game. Apa itu tekstur? Rekan-rekan dapat melihat gambar di bawah ini. Gambar di bawah adalah gambar dua buah kotak.  


 Jika kotak-kotak tersebut diberi tekstur akan menjadi seperti di bawah ini.


Gimana keren kan? Teknik pemberian tekstur seperti ini juga berlaku untuk grafik 3D, jadi sangat bermanfaat. Ingin lanjut ato sampe disini aja? Lanjut ya.

Tekstur yang digunakan untuk memberi kulit pada kotak-kotak di atas berasal  dari file bitmap 24 bit. File tersebut di konversi menjadi tekstur lalu direkatkan ke kotak-kotak tersebut. Itu dia teorinya, sederhana sekali. Lalu bagaimana caranya?

Program pemberian tekstur objek 2D ini menggunakan Empty Project, bagi rekan-rekan yang belum pernah membuat program OpenGL 2D dengan Empty Project silahkan klik link ini dahulu. Bagi rekan-rekan yang telah paham silahkan lanjut.

Gunakan fungsi berikut ini untuk mengubah file bitmap 24 bit menjadi sebuah tekstur.

//digunakan untuk membuat tekstur dari file bitmap 24 bit
unsigned int Create_Texture(char *filename)
{
    AUX_RGBImageRec *My_Texture;
    unsigned int My_IDTexture;

    My_Texture = auxDIBImageLoad(filename);

    if (My_Texture != NULL)
    {
        glGenTextures(1, &My_IDTexture);

        glBindTexture(GL_TEXTURE_2D, My_IDTexture);

        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB,
            My_Texture->sizeX, My_Texture->sizeY,
            GL_RGB, GL_UNSIGNED_BYTE,
            My_Texture->data);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
            My_Texture->sizeX, My_Texture->sizeY,
            0, GL_RGB, GL_UNSIGNED_BYTE,
            My_Texture->data);

        free(My_Texture);

        return My_IDTexture;
    }

    return NULL;
}

 Load file bitmap yang hendak dijadikan tekstur.

//load file bitmap 24 bit
bool Load_Texture()
{
    glEnable(GL_TEXTURE_2D);

    if ((texture_biru = Create_Texture("Bmp_Files/Text_biru.bmp")) == NULL)
        return false;

    if ((texture_merah = Create_Texture("Bmp_Files/Text_merah.bmp")) == NULL)
        return false;

    return true;
}

Lalu rekatkan tekstur tersebut ke objek 2D dengan cara seperti berikut. Fungsi glTexCoord2d menggunakan koordinat kartesius (X, Y) untuk melakukan mapping ke objek 2D, dan jangan lupa ganti glBegin(GL_LINE_LOOP) menjadi glBegin(GL_POLYGON).



    //Kotak biru
    glBindTexture(GL_TEXTURE_2D, texture_biru);
    glBegin(GL_POLYGON);
    //titik kiri bawah
    glTexCoord2d(0.0, 0.0);
    glVertex2d(-500.0, -100.0);
    //titik kanan bawah
    glTexCoord2d(1.0, 0.0);i
    glVertex2d(100.0, -100.0);
    //titik kanan atas
    glTexCoord2d(1.0, 1.0);
    glVertex2d(100.0, 300.0);
    //titik kiri atas
    glTexCoord2d(0.0, 1.0);
    glVertex2d(-500.0, 300.0);
    glEnd();

Sederhana bukan tapi besar manfaatnya. Berikut ini ogut sertakan kode program secara lengkap, silahkan di copy paste ngak perlu bayar dan boleh cantumin author ato tidak ngak masalah buat ogut.

//berguna untuk memangkas library
//yang tidak terpakai
#define WIN32_LEAN_AND_MEAN    
#define VC_LEANMEAN    
#define VC_EXTRALEAN       

//include yang harus disertakan
#include<windows.h>
#include<stdio.h>          
#include<stdlib.h>
#include<mmsystem.h>

//include khusus OpenGL
#include<gl/gl.h>               
#include<gl/glu.h>
#include "glaux/glaux.h" //header ini ada di dalam folder GLAUX

//library untuk OpenGL
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "GLAUX/glaux.lib") //library ini ada di dalam folder GLAUX

//Variable global yang dipakai untuk program ini
HDC My_HDC_Global;

//set tinggi dan lebar untuk window screen
unsigned int tinggi_window_Screen = 600;
unsigned int lebar_window_Screen = 800;

//penempatan posisi window screen di monitor
unsigned int X_window_Screen = 150;
unsigned int Y_window_Screen = 50;

//berguna untuk setup pixel
//dengan sistem koordinat kartesius 2D
double Xmax = 800.0;
double Ymax = 600.0;

//variable Texture
unsigned int texture_biru;
unsigned int texture_merah;

//+++++++++++++++++++++++++++++++++++++++++++
//untuk membuat program grafik dengan OpenGL
//hanya dibutuhkan empat buah fungsi, dengan
//WinMain sebagai fungsi utama (WinMain 1 fungsi tambah 3 fungsi dibawah ini jadi 4 semuanya)
LRESULT CALLBACK My_WindowProc(HWND hwnd_p, UINT message_p, WPARAM wparam_p, LPARAM lparam_p);
void Window_Pixel_Format(HDC hdc_GPF_p);
void Display_Grafik();

unsigned int Create_Texture(char *filename);
bool Load_Texture();

//+++++++++++++++++++++++++++++++++++++++++++

//fungsi yang dipanggil pertama kali
//oleh Operating system Windows, pada
//saat program dijalankan
int WINAPI WinMain(HINSTANCE hinstance_p, HINSTANCE hprevinstance_p, LPSTR lpcmdline_p, int nshowcmd_p)
{
    MSG My_MSG;
    WNDCLASSEX My_WNDCLASSEX;
    HWND My_HWND;
    bool My_MainLoop = false;

    //deklarasi variable untuk membuat window
    My_WNDCLASSEX.cbSize = sizeof(WNDCLASSEX);
    My_WNDCLASSEX.style = CS_HREDRAW | CS_VREDRAW;

    //My_WindowProc adalah fungsi yang kita buat
    //untuk memproses message-message,
    //fungsi ini yang terus menerus akan dipanggil
    //oleh fungsi WinMain, sehingga harus kita
    //daftarkan di bawah ini
    My_WNDCLASSEX.lpfnWndProc = My_WindowProc;

    My_WNDCLASSEX.cbClsExtra = 0;
    My_WNDCLASSEX.cbWndExtra = 0;
    My_WNDCLASSEX.hInstance = hinstance_p;
    My_WNDCLASSEX.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    My_WNDCLASSEX.hCursor = LoadCursor(NULL, IDC_WAIT);
    My_WNDCLASSEX.hbrBackground = NULL;
    My_WNDCLASSEX.lpszMenuName = NULL;
    My_WNDCLASSEX.lpszClassName = "MyOpenGL";
    My_WNDCLASSEX.hIconSm = LoadIcon(NULL, IDI_WINLOGO);

    //register window Class
    //jika terjadi error program dihentikan
    if (!RegisterClassEx(&My_WNDCLASSEX))
    {
        MessageBox(NULL,
            "Register Window Class Failed", "Window Error", MB_OK);
        return 0;
    }

    //jika register window class berhasil
    //lanjutkan dengan create window
    My_HWND = CreateWindowEx(
        NULL,
        "MyOpenGL",
        "Heriady Blog heriadyblog.blogspot.com (Esc to quit)",
        NULL,
        X_window_Screen,
        Y_window_Screen,
        lebar_window_Screen,
        tinggi_window_Screen,
        NULL,
        NULL,
        hinstance_p,
        NULL);

    //jika window tidak bisa di-create
    //program dihentikan
    if (!My_HWND)
    {
        MessageBox(NULL,
            "Failed to Create Window", "Window Error", MB_OK);
        return 0;
    }

    //load all texture here
    if (!Load_Texture())
        return 0;

    //jika window bisa di-create
    //tampilkan window ke monitor
    ShowWindow(My_HWND, SW_SHOW);
    UpdateWindow(My_HWND);

    //Looping utama
    while (!My_MainLoop)
    {
        //proses message dari antrian
        PeekMessage(&My_MSG, 0, 0, 0, PM_REMOVE);

        //selama tidak ada message 'Quit'
        //looping akan terus berjalan
        if (My_MSG.message != WM_QUIT)
        {
            //panggil fungsi untuk render window
            //disini
            Display_Grafik();

            //translate Virtual key message,
            //menjadi chararcter message dan
            //buang message yang sudah diproses
            TranslateMessage(&My_MSG);
            DispatchMessage(&My_MSG);
        }
        else
            //jika message = 'Quit'
            //keluar dari looping
            My_MainLoop = true;


    } //while (!My_MainLoop)

    //unregister window class
    UnregisterClass("MyOpenGL", My_WNDCLASSEX.hInstance);

    //akhiri program
    return (int)My_MSG.wParam;
}

//fungsi yang dipanggil oleh WinMain
//untuk memproses message-message
LRESULT CALLBACK My_WindowProc(HWND hwnd_p, UINT message_p, WPARAM wparam_p, LPARAM lparam_p)
{
    static HGLRC My_HGLRC;
    static HDC My_HDC;

    //pada saat window dibuat pertama kali
    //kondisi if di bawah memenuhi
    if (message_p == WM_CREATE)
    {
        My_HDC = GetDC(hwnd_p);
        My_HDC_Global = My_HDC;

        //pada saat pertama kali dibuat 
        //window screen harus di setup pixel
        //agar bisa dibuat untuk tampilan grafik
        Window_Pixel_Format(My_HDC);

        My_HGLRC = wglCreateContext(My_HDC);
        wglMakeCurrent(My_HDC, My_HGLRC);

        return 0;
    }

    //pada saat program hendak keluar
    //kondisi if di bawah memenuhi
    if (message_p == WM_DESTROY)
    {
        wglMakeCurrent(My_HDC, NULL);
        wglDeleteContext(My_HGLRC);
        PostQuitMessage(0);

        return 0;
    }

    //untuk saat window dibuat pertama kali atau
    //window diubah ukurannya.
    //pada program ini ukuran window
    //tidak bisa diubah, tetapi kondisi if
    //di bawah harus tetap di pasang
    if (message_p == WM_SIZE)
    {
        //fungsi OpenGL untuk set
        //tinggi dan lebar window screen
        glViewport(0, 0, lebar_window_Screen, tinggi_window_Screen);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        //fungsi untuk membuat sistem
        //koordinat kartesius 2D
        // -X = -800, X = +800 dan,
        // -Y = -600, Y = +600
        gluOrtho2D(-Xmax, Xmax, -Ymax, Ymax);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        //warna latar belakang hitam
        glClearColor(0.0, 0.0, 0.0, 0.0);

        return 0;
    }

    //tombol ESC ditekan
    //untuk keluar dari program
    if ((message_p == WM_KEYDOWN) && (wparam_p == VK_ESCAPE))
    {
        //fungsi untuk mengirimkan
        //message WM_QUIT
        PostQuitMessage(0);

        return 0;
    }

    //return kembali nilai LRESULT
    return (DefWindowProc(hwnd_p, message_p, wparam_p, lparam_p));
}

//fungsi untuk setup pixel, yang
//dipakai untuk program grafik,
//fungsi ini harus ada jika hendak membuat
//program grafik
void Window_Pixel_Format(HDC hdc_GPF_p)
{
    int My_Pixel_Format;

    static PIXELFORMATDESCRIPTOR My_PFD =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW |
        PFD_SUPPORT_OPENGL |
        PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        16,
        0, 0, 0, 0, 0, 0,
        0,
        0,
        0,
        0, 0, 0, 0,
        16,
        0,
        0,
        PFD_MAIN_PLANE,
        0,
        0, 0, 0
    };

    My_Pixel_Format = ChoosePixelFormat(hdc_GPF_p, &My_PFD);

    SetPixelFormat(hdc_GPF_p, My_Pixel_Format, &My_PFD);
}

//load file bitmap 24 bit
bool Load_Texture()
{
    glEnable(GL_TEXTURE_2D);

    if ((texture_biru = Create_Texture("Bmp_Files/Text_biru.bmp")) == NULL)
        return false;

    if ((texture_merah = Create_Texture("Bmp_Files/Text_merah.bmp")) == NULL)
        return false;

    return true;
}

//digunakan untuk membuat tekstur dari file bitmap 24 bit
unsigned int Create_Texture(char *filename)
{
    AUX_RGBImageRec *My_Texture;
    unsigned int My_IDTexture;

    My_Texture = auxDIBImageLoad(filename);

    if (My_Texture != NULL)
    {
        glGenTextures(1, &My_IDTexture);

        glBindTexture(GL_TEXTURE_2D, My_IDTexture);

        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB,
            My_Texture->sizeX, My_Texture->sizeY,
            GL_RGB, GL_UNSIGNED_BYTE,
            My_Texture->data);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
            My_Texture->sizeX, My_Texture->sizeY,
            0, GL_RGB, GL_UNSIGNED_BYTE,
            My_Texture->data);

        free(My_Texture);

        return My_IDTexture;
    }

    return NULL;
}

//fungsi yang dipakai untuk menampilkan
//semua object(Polygon) yang akan kita buat
//pada window screen
void Display_Grafik()
{
    //clear buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    //...........................
    //display object  di sini
    //...........................

    //Kotak biru
    glBindTexture(GL_TEXTURE_2D, texture_biru);
    glBegin(GL_POLYGON);
    //titik kiri bawah
    glTexCoord2d(0.0, 0.0);
    glVertex2d(-500.0, -100.0);
    //titik kanan bawah
    glTexCoord2d(1.0, 0.0);
    glVertex2d(100.0, -100.0);
    //titik kanan atas
    glTexCoord2d(1.0, 1.0);
    glVertex2d(100.0, 300.0);
    //titik kiri atas
    glTexCoord2d(0.0, 1.0);
    glVertex2d(-500.0, 300.0);
    glEnd();

    //Kotak merah (tektur di ulang dengan mengubah nilai X di fungsi glTexCoord2d)
    glBindTexture(GL_TEXTURE_2D, texture_merah);
    glBegin(GL_POLYGON);
    //titik kiri bawah
    glTexCoord2d(0.0, 0.0);
    glVertex2d(-200.0, -400.0);
    //titik kanan bawah
    glTexCoord2d(2.0, 0.0);
    glVertex2d(400.0, -400.0);
    //titik kanan atas
    glTexCoord2d(2.0, 1.0);
    glVertex2d(400.0, -200.0);
    //titik kiri atas
    glTexCoord2d(0.0, 1.0);
    glVertex2d(-200.0, -200.0);
    glEnd();

    //fungsi swapbuffer harus dipasang pada akhir Display_Grafik()
    SwapBuffers(My_HDC_Global);
}

Terima kasih kepada rekan-rekan yang telah membaca artikel ini, sayonara.


Heriady
heriady.yoh@gmail.com


Download link program ini supaya ngak capek ngetik dan tinggal run, selamat belajar.


Artikel terkait
Membuat file bitmap 24 bit dengan Paint
Program OpenGL 2D dengan Empty Project