Pada praktikum 5 menpelajari tentang tekstur proseduran serta perbedaannya dengan tekstur 2D. Kemudian menerapkan tekstur procedural tersebut pada objek dengan OpenGL. Tekstur procedural yaitu sebuah fungsi yang menghitung koordinat tekstur dan tekstur tersebut dapat dibuat menggunakan fungsi procedural, misal seperti tekstur pola kayu, marble dan lan-lain. Itu dapat menggunakan fungsi sinus harmonic yang diberi noise, tekstur langit, tekstur pola kayu dan lain sebagainya.
Tekstur prosedural juga mempuyai berbagai keuntungan seperti menghindari perhitungan trasformasi tekstur dari koordinat citra 2D ke permukaan objek. Keuntungan tersebut salah satunya yaitu trasformasi tekstur tersebut hanya membutuhkan ruang penyimpanan yang kecil dan dapat divariasikan sesuai dengan kebutuhan.
Source Code :
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <glut.h>
#include <GLAux.h>
#include "praktikum05_addon.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;
// penyimpanan tekstur
// dalam hal ini satu tekstur saja
GLuint texture[1];
const int texWidth = 512; // panjang ukuran tekstur
const int texHeight = 512; // lebar ukuran tekstur
char texData[texWidth][texHeight][3]; // alokasi memori untuk tekstur 3D
double noiseData[texWidth][texHeight]; // alokasi memori untuk noise 2D
// fungsi untuk membangkitkan noise
void genNoise()
{
for (int i = 0; i < texHeight; i++)
{
for (int j = 0; j < texWidth; j++)
noiseData[i][j] = (rand() % 32768) / 32768.0;
}
}
// fungsi untuk menghaluskan noise
double smoothNoise(double x, double y)
{
// hitung nilai selisih fraksi dari x dan y
double fractX = x - int(x);
double fractY = y - int(y);
// hitung jumlah langkah
int x1 = (int(x) + texWidth) % texWidth;
int y1 = (int(y) + texHeight) % texHeight;
// hitung nilai ketetanggaan
int x2 = (x1 + texWidth - 1) % texWidth;
int y2 = (y1 + texHeight - 1) % texHeight;
// haluskan noise
double value = 0.0;
value += fractX * fractY * noiseData[y1][x1];
value += (1 - fractX) * fractY * noiseData[y1][x2];
value += fractX * (1 - fractY) * noiseData[y2][x1];
value += (1 - fractX) * (1 - fractY) * noiseData[y2][x2];
return value;
}
// fungsi untuk memberi turbulensi pada noise
double turbNoise(double x, double y, double size)
{
double value = 0.0, initialSize = size;
while (size >= 1)
{
value += smoothNoise(x / size, y / size) * size;
size /= 2.0;
}
return(128.0 * value / initialSize);
}
// fungsi untuk melakukaan pemetaan tekstur
int setTextures()
{
int status = FALSE;
// buat alokasi untuk teksturnya
glGenTextures(1, texture);
// buat tekstur dengan fungsi perlin
float perlinData;
for (int i = 0; i < texHeight; i++)
{
for (int j = 0; j < texWidth; j++)
{
// tekstur rumput dengan perlin noise
perlinData = perlinNoise2D(i, j, 0.1f, 0.9f, 8.0f);
texData[i][j][0] = (char)perlinData / 64;
texData[i][j][1] = (char)perlinData;
texData[i][j][2] = (char)perlinData / 64;
}
}
status = TRUE;
// bind tekstur dari fungsi perlin tadi
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, texWidth, texHeight, 0, GL_RGB,
GL_UNSIGNED_BYTE, texData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return status;
}
// fungsi untuk menggambar obyek
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);
// menggambar obyek diawali glBegin(tipe obyek) dan diakhiri dengan glEnd()
// kecuali menggunakan fungsi yang sudah ada di GLUT-OpenGL
// sisi depan kotak
glBindTexture(GL_TEXTURE_2D, texture[0]); // bind tekstur dari tekstur pertama
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
//sisi belakang kotak
glBindTexture(GL_TEXTURE_2D, texture[0]); // bind tekstur dari tekstur pertama
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
// sisi samping kanan kotak
glBindTexture(GL_TEXTURE_2D, texture[0]); // bind tekstur dari tekstur pertama
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glEnd();
// sisi samping kiri kotak
glBindTexture(GL_TEXTURE_2D, texture[0]); // bind tekstur dari tekstur pertama
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glEnd();
// sisi bawah kotak
glBindTexture(GL_TEXTURE_2D, texture[0]); // bind tekstur dari tekstur pertama
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glEnd();
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();
// 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();
}
// 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 tekstur
glEnable(GL_TEXTURE_2D);
}
// 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_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 05 - Imam Muamar Kharisma - 1502318006");
printf("PRAKTIKUM 05\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
// set tekstur dengan citra yang sudah disediakan
int status = setTextures();
// looping
glutMainLoop();
return 0;
}
Screenshot
0 komentar: