Pada praktikum 03 Grafika Lanjut mahasiswa dituntut agar mampu menjelaskan model-model shading dan cara penerapannya dengan OpenGL.
Melanjutkan pada praktikum 1 yang
mengunakan fungsi glutSolidTeaport untuk menggambar object teko, pada praktikum
3 fungsi tersebut dirubah menjadi glutSolidSphere untuk menampilkan objek
berupa bola. Selanjutnya ada beberapa file tambahan pada folder resource fies
visual c++ yaitu file praktikum03_goraud.vert, praktikum03_goraud.frag, praktikum03_phong.vert
dan praktikum03_phong.frag.
Pada openGL model shading yang
umum digunakan yaitu Goraud shading dan phong shading. Pada praktikum 3 ini
juga mempelajari phong shading. Seperti
yang sudah dijelaskan pada modul. Bahwa phong shading menampilkan yang lebih
baik dari garaud shading. Hal itu dikarenakan pada Goraud shading objek
ditampilkan ditampilkan dengan cara menghitung nilai cahaya per vertex lalu
menginterpolasi hasil tersebut sebagai nilai shading. Sedangkan phong shading
melakukan interpolasi permukaan normal antar vetex kemudian menggunakan
hasilnya untuk menghitung nilai pencahayaan disetiap piksel bukan di setiap
vertex seperti Goraud Shading.
Contoh Program
#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;
float posX = 0.0f, rotX = 0.0f;
float posY = 0.0f, rotY = 0.0f;
float posZ = 5.0f, rotZ = -1.0f;
float objectAngle = 0.0f;
float objectPosX = 0.0f;
float objectPosY = 0.0f;
float objectPosZ = 0.0f;
// saklar untuk mematikan / menghidupkan pencahayaan
bool light0 = false;
//
float matShininess[] = { 128.0 }; // kekuatan specular cahaya
float matAmbient[] = { 0.5, 0.5, 0.5, 0.0 }; // material cahaya sekitar
float matDiffuse[] = { 0.5, 0.2, 0.7, 0.0 }; // material cahaya tersebar
float matSpecular[] = { 0.7, 0.7, 0.7, 0.0 }; // material cahaya biasa
float lightPosition0[] = { 10.0, 10.0, 10.0, 1.0 }; // posisi sumber cahaya 1
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 me-load shaders
void setShaders()
{
char* vertex = readShaders("praktikum03_goraud.vert");
char* fragment = readShaders("praktikum03_goraud.frag");
char* vertex1 = readShaders("praktikum03_phong.vert");
char* fragment1 = readShaders("praktikum03_phong.frag");
vertexShaders = glCreateShader(GL_VERTEX_SHADER);
fragmentShaders = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vertexShaders, 1, (const char**)&vertex, 0);
glShaderSource(fragmentShaders, 1, (const char**)&fragment, 0);
glShaderSource(vertexShaders, 1, (const char**)&vertex1, 0);
glShaderSource(fragmentShaders, 1, (const char**)&fragment1, 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);
free(vertex1);
free(fragment1);
}
// 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 ke arah sumbu X (gunakan bila perlu)
glRotatef(objectAngle, objectPosX, objectPosY, objectPosZ);
// set warna obyek ke warna magenta (1, 0, 1)
glColor3f(1.0f, 0.0f, 1.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
//glutSolidSphere(1.0f, 50, 50);
// post test
glutSolidSphere(1.0f, 50, 50);
glPopMatrix();
}
// taruh semua obyek yang akan digambar di fungsi display()
void display()
{
// bersihkan layar dan buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glShadeModel(GL_SMOOTH);
glShadeModel(GL_FLAT);
// set material dan posisi sumber cahaya
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0); // set posisi sumber cahaya 0
glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbient); // set material permukaan model ambient
glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiffuse); // set material permukaan model diffuse
glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular); // set material permukaan model specular
glMaterialfv(GL_FRONT, GL_SHININESS, matShininess); // set material permukaan mengkilat
if (light0)
glDisable(GL_LIGHT0);
else
glEnable(GL_LIGHT0);
// 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);
// terapkan shading
glShadeModel(GL_FLAT); // flat shading
//glShadeModel(GL_SMOOTH); // interpolative shading
// panggil fungsi untuk menggambar obyek
drawObject();
// tampilkan obyek ke layar
// gunakan glFlush() bila memakai single buffer
// gunakan glutSwapBuffers() bila memakai double buffer
glutSwapBuffers();
}
// inisialisasi variabel, pencahayaan, tekstur dan pengaturan kamera pandang di fungsi init()
void init(void)
{
// inisialisasi warna background layar
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();
// set kamera pandang awal
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// aktifkan pencahayaan dan warna material
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); // sumber cahaya pertama (maksimal 8 sumber cahaya)
glEnable(GL_COLOR_MATERIAL);
}
// 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, dan bawah
void keyboard(int key, int x, int y)
{
float fraction = 0.1f;
switch (key)
{
case GLUT_KEY_F1:
// masukkan perintah disini bila tombol F1 ditekan
light0 = !light0; // matikan / hidupkan sumber cahaya 0
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
// masukkan perintah disini bila tombol kiri ditekan
// 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;
case GLUT_KEY_RIGHT:
// masukkan perintah disini bila tombol kanan ditekan
// 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;
case GLUT_KEY_UP:
// masukkan perintah disini bila tombol atas ditekan
// 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;
case GLUT_KEY_DOWN:
// masukkan perintah disini bila tombol bawah ditekan
// 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);
}
// 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_RGB | 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 3 - IMAM MUAMAR KHARISMA - 1501318006");
printf("PRAKTIKUM 3\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));
// aktifkan atau matikan untuk menggunakan shader
//setShaders();
// looping
glutMainLoop();
return 0;
}
Hasil
0 komentar: