Kamis, 17 November 2016

OpenGL, Shader dan Tipe Shaders

Pada kesempatan kali ini. Saya akan share praktikum 01 mata kuliah Grafika Lanjut. 

Pada komputer grafis, kode atau sebuah program yang telah dibuat menggunakan openGL akan dikirimkan ke perangkat keras (hardware) grafis. Lalu didalam hardware grafis tersebut, instruksi kode akan diproses secara parallel oleh GPU. Apa itu GPU ? GPU itu singkatan dari Graphics Processing Unit. Pada GPU ini terdapat banyak sekali procesor yang disebut dengan inti shaders atau shaders cores. Fungsinya yaitu untuk menjalankan program yang disebut dengan shaders.

OpenGl shader ini ditulis menggunakan bahasa yang disebut dengan OpenGL Shading Language atau biasa disingkat dengan GLSL. Bahasa ini sebetulnya ditulis menggunakan bahasa C akan tetapi sudah dimodifikasi. Tujuan modifikasi tersebut yaitu untuk memudahkan penggunaannya. Pada praktikum 01 ini saya mempelajari bagaimana menuliskan kode pada shader terutama vertex shader dan fragment shader untuk memodifikasi sebuah obyek. 

Ok. Langsung saja berikut ini contoh program dan hasil runningnya. 



// deklarasikan semua header disini
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <glew.h>
#include <glut.h>

// inisialisasi variabel untuk transformasi seperti translasi, rotasi atau scaling
// (gunakan bila perlu)
float angle = 0.0f; // sudut transformasi kamera
float posX = 0.0f, rotX =  0.0f; // posisi kamera di sumbu X
float posY = 0.0f, rotY =  0.0f; // posisi kamera di sumbu Y
float posZ = 5.0f, rotZ = -1.0f; // posisi kamera di sumbu Z

float objectAngle = 0.0f; // sudut tranformasi obyek
float objectPosX = 0.0f; // posisi obyek di sumbu X
float objectPosY = 0.0f; // posisi obyek di sumbu Y
float objectPosZ = 0.0f; // posisi obyek di sumbu Z

// fungsi untuk menggambar obyek kubus
void drawObject()
{
// obyek bisa dimasukkan diantara glPushMatrix() dan glPopMatrix() 
// fungsinya agar obyek tidak terpengaruh atau mempengaruhi obyek lain
// saat diwarnai, ditransformasi dan sebagainya
glPushMatrix();

// operasi transformasi rotasi obyek ke arah sumbu X, Y atau Z (gunakan bila perlu)
glRotatef(objectAngle, objectPosX, objectPosY, objectPosZ);

// set warna obyek ke warna hijau (0.0f, 1.0f, 0.0f)
glColor3f(0.0f, 1.0f, 0.0f);

// bila menggambar obyek harus diawali glBegin(tipe obyek) dan diakhiri dengan glEnd()
// kecuali menggunakan fungsi yang sudah ada di GLUT-OpenGL seperti dibawah ini
glutSolidTeapot(1.0f); // menggambar obyek kubus

glPopMatrix();
}

// taruh semua obyek yang akan digambar di fungsi display()
void display()
{
// bersihkan dan reset layar dan buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

// posisikan kamera pandang
// dalam hal ini sumbu Y ada diatas dan posisi kamera pandang di (posX, posY, posZ)
gluLookAt(posX, posY, posZ, posX + rotX, posY + rotY, posZ + rotZ, 0.0f, 1.0f, 0.0f);

// panggil fungsi untuk menggambar obyek
drawObject();
// tampilkan obyek ke layar
// gunakan glFlush() bila memakai single buffer
// gunakan glutSwapBuffers() bila memakai double buffer
glutSwapBuffers();
}

// inisialisasikan variabel, pencahayaan, tekstur dan pengaturan kamera pandang di fungsi init()
void init(void)
{
// inisialisasi warna latar belakang layar dalam hal ini warna putih (1.0, 1.0, 1.0, 0.0)
glClearColor(1.0, 1.0, 1.0, 0.0);
glEnable(GL_DEPTH_TEST); // mengaktifkan depth buffer
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, 1.0, 1.0, 100.0); // set proyeksi ke perspektif
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// inisialisasi kamera pandang
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

// fungsi ini digunakan bila layar akan diresize (default)
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}

// fungsi untuk mengatur masukan dari keyboard untuk arah kiri, kanan, atas, bawah, F1 dan F2
void keyboard(int key, int x, int y)
{
float fraction = 0.1f;

switch (key) 
{
// masukkan perintah disini bila tombol kiri ditekan
case GLUT_KEY_LEFT:
// dalam hal ini perintah rotasi obyek ke kiri sebanyak 1 derajat 
objectAngle -= 1.0f;
objectPosX = 0.0f;
objectPosY = 1.0f;
objectPosZ = 0.0f;
glutPostRedisplay(); // update obyek
break;
// masukkan perintah disini bila tombol kanan ditekan
case GLUT_KEY_RIGHT:
// dalam hal ini perintah rotasi obyek ke kanan sebanyak 1 derajat 
objectAngle += 1.0f;
objectPosX = 0.0f;
objectPosY = 1.0f;
objectPosZ = 0.0f;
glutPostRedisplay(); // update obyek
break;
// masukkan perintah disini bila tombol atas ditekan
case GLUT_KEY_UP:
// dalam hal ini perintah rotasi obyek ke atas sebanyak 1 derajat 
objectAngle -= 1.0f;
objectPosX = 1.0f;
objectPosY = 0.0f;
objectPosZ = 0.0f;
glutPostRedisplay(); // update obyek
break;
// masukkan perintah disini bila tombol bawah ditekan
case GLUT_KEY_DOWN:
// dalam hal ini perintah rotasi obyek ke bawah sebanyak 1 derajat 
objectAngle += 1.0f;
objectPosX = 1.0f;
objectPosY = 0.0f;
objectPosZ = 0.0f;
glutPostRedisplay(); // update obyek
break;
// zoom in
case GLUT_KEY_PAGE_UP:
// masukkan perintah disini bila tombol PgUp ditekan
posX += rotX * fraction;
posZ += rotZ * fraction;
glutPostRedisplay(); // update obyek
break;
// zoom out
case GLUT_KEY_PAGE_DOWN:
// masukkan perintah disini bila tombol PgDn ditekan
posX -= rotX * fraction;
posZ -= rotZ * fraction;
glutPostRedisplay(); // update obyek
break;
}
}

// timer untuk animasi (gunakan bila perlu)
void timer(int value)
{
glutPostRedisplay();
glutTimerFunc(55, timer, 0);
}

GLuint vertexShaders, fragmentShaders, programShaders;
// fungsi membaca file shader 
char* readShaders(char *file) 
FILE *fptr; 
long length; 
char *buf;

fopen_s(&fptr, file, "rb"); // buka file 
if (!fptr) 
return NULL; 
fseek(fptr, 0, SEEK_END); 
length = ftell(fptr); 
buf = (char*)malloc(length + 1); // buat buffer untuk menyimpan file 
fseek(fptr, 0, SEEK_SET); 
fread(buf, length, 1, fptr); // baca konten 
fclose(fptr); // tutup file 
buf[length] = 0;
return buf; 
}

// fungsi untuk membaca shaders 
void setShaders() 
char* vertex = readShaders("PRAKTIKUM-1.vert"); // baca vertex shaders 
char* fragment = readShaders("PRAKTIKUM-1.frag"); // baca fragment shaders 
vertexShaders = glCreateShader(GL_VERTEX_SHADER); 
fragmentShaders = glCreateShader(GL_FRAGMENT_SHADER); 
glShaderSource(vertexShaders, 1, (const char**)&vertex, 0); 
glShaderSource(fragmentShaders, 1, (const char**)&fragment, 0); 
glCompileShader(vertexShaders); 
glCompileShader(fragmentShaders);

programShaders = glCreateProgram(); 
glAttachShader(programShaders, vertexShaders); 
glAttachShader(programShaders, fragmentShaders); 
glBindAttribLocation(programShaders, 0, "in_Position"); 
glBindAttribLocation(programShaders, 1, "in_Color"); 
glLinkProgram(programShaders); 
glUseProgram(programShaders);

free(vertex); 
free(fragment); 
}

// program utama
int main(int argc, char** argv)
{
// inisialisasi jendela OpenGL
// GLUT_SINGLE berarti memakai single buffer
// GLUT_DOUBLE berarti memakai double buffer
// GLUT_RGB berarti mode tampilan yang dipakai RGB
// GLUT_RGBA berarti mode tampilang yang dipakai RGBA
// GLUT_DEPTH berarti memakai depth buffer
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

// set ukuran jendela tampilan
glutInitWindowSize(480, 480); // besarnya jendela dalam piksel dalam hal ini 300x300
glutInitWindowPosition(100, 100); // posisi jendela dilayar komputer dalam piksel
// judul jendela (wajib diubah dengan informasi NAMA / NIM - JUDUL PRAKTIKUM masing-masing)
glutCreateWindow("PRAKTIKUM 1 - IMAM MUAMAR KHARISMA - 1501318006");
printf("PRAKTIKUM 01\n "); 
printf("Imam Muamar Kharisma \n "); 
printf("\n "); 
printf("\n "); 
printf("\n "); 
printf("\n "); 
// panggil fungsi init untuk inisialisasi awal
init();

// event handler untuk display, reshape dan keyboard
glutDisplayFunc(display);   // display
glutReshapeFunc(reshape);   // reshape
glutSpecialFunc(keyboard);  // keyboard
//glutTimerFunc(0, timer, 0); // aktifkan timer bila perlu

// inisialisasi glew 
// cek apakah glew bisa digunakan 
GLenum err = glewInit(); 
if (GLEW_OK != err)
fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); 
else 
fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
setShaders();
// looping
glutMainLoop();

return 0;
}

Screen Shoot 


Semoga bermanfaat ya. 



Previous Post
Next Post

post written by:

0 komentar: