Tutorial 08. Fog Kabut/fog adalah salah satu fitur OpenGL lain yang sering digunakan pada banyak kesempatan. Kabut digunakan dalam banyak kesempatan, antara lain:
•
mensimulasikan efek kabut
•
membatasi ruang pandang pengguna agar komputasi grafis yang diperlukan dapat dibatasi.
Hal ini terutama dilakukan pada era-era ketika algoritma grafis masih dilakukan di CPU. Program 11 memperlihatkan bagaimana menggunakan fungsi-fungsi OpenGL yang terkait dengan fog. // Fog // Program ini menampilkan efek kabut (fog) // Image Loadernya menggunakan library tambahan yaitu SOIL (Simple OpenGL Image Library) //
Untuk
mendapatkan
glenable(GL_FOG); #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include "SOIL.h" #include
efek
kabut
menggunakan
perintah
float z_pos = -5.0f; float Rot = 0.0f;
GLfloat LightAmbient[] = {0.5f, 0.5f, 0.5f, 1.0f}; GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; GLfloat LightPosition[] = {0.0f, 0.0f, 2.0f, 1.0f}; // storage for one texture GLuint tex_2d; /* storage for three texture
*/
GLuint filter; GLuint texture[3]; // Fog GLuint fogFilter; GLuint fogMode[] = {GL_EXP, GL_EXP2, GL_LINEAR}; GLfloat fogColor[4] = {0.5f, 0.5f, 0.5f, 1.0f};
GLuint* LoadGLTextures(); void init(); void myKeyboard(unsigned char, int, int); void myDisplay(void); void myTimeOut(int); void resize(int, int);
int main(int argc, char* argv[]) { glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(500, 500); glutInitWindowPosition(0, 0); glutCreateWindow("Fog"); glutDisplayFunc(myDisplay); glutIdleFunc(myDisplay); glutKeyboardFunc(myKeyboard); glutReshapeFunc(resize); glutTimerFunc(100, myTimeOut, 0); init(); glutMainLoop(); return 0; } GLuint LoadGLTextures(GLint filter) Load Bitmaps And Convert To Textures { /* load an image file directly as a new OpenGL texture */ tex_2d = SOIL_load_OGL_texture("3.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT); /* check for an error during the load process */ if(tex_2d == 0) { printf( "SOIL loading error: '%s'\n", SOIL_last_result() ); } if(filter == 0)
//
{ // Create Nearest Texture Filter glBindTexture(GL_TEXTURE_2D, tex_2d); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEARES T); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEARES T); } else if(filter == 1) { // Create Linear Texture Filter glBindTexture(GL_TEXTURE_2D, tex_2d); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR ); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR ); }else { // Create MipMapped Texture Filter glBindTexture(GL_TEXTURE_2D, tex_2d); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR ); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR _MIPMAP_NEAREST); } return tex_2d; Success } void init() { for(int i = 0; i < 3; ++i)
// Return
{ texture[i] = LoadGLTextures(i); } glEnable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
// Clear to color
of the Fog glFogi(GL_FOG_MODE, fogMode[fogFilter]);
// Fog Mode
glFogfv(GL_FOG_COLOR, fogColor);
// Set Fog Color
glFogf(GL_FOG_DENSITY, 0.5f);
// How Dense will
the color be glHint(GL_FOG_HINT, GL_DONT_CARE);
// Fog Hint Value
glFogf(GL_FOG_START, 100.0f);
// Fog Start
Depth glFogf(GL_FOG_END, 1000.0f);
// Fog End Depth
glEnable(GL_FOG);
// Enable Fog
glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); glEnable(GL_LIGHT1); } void myKeyboard(unsigned char key, int x, int y) { switch(key) { case '<':
case ',': z_pos -= 0.1f; break; case '>': case '.': z_pos += 0.1f; break; case 'F': case 'f': filter += 1; if(filter > 2) { filter = 0; } printf("filter: %i \n", filter); break; case 'G': case 'g': fogFilter += 1; if(fogFilter > 2)
// Is
fogFilter greater than 2? { fogFilter = 0;
// If so,
set fogFilter to Zero } glFogi(GL_FOG_MODE, fogMode[fogFilter]); Mode printf("fogfilter : %i \n", fogFilter); break; case 27:
// Fog
exit(0); break; default: break; } } void myDisplay(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glLoadIdentity(); glTranslatef(0.0f, 0.0f, z_pos); //
glRotatef(Rot, 0.0f, 1.0f, 0.0f);
// Rotate On The X Axis
//glBindTexture(GL_TEXTURE_2D, tex_2d1[0]); glBindTexture(GL_TEXTURE_2D, texture[filter]); glBegin(GL_QUADS); // Front Face glNormal3f( 0.0f, 0.0f, 1.0f); 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);
// Back Face glNormal3f( 0.0f, 0.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);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Face
glNormal3f( 0.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,
1.0f, -1.0f);
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);
// Bottom Face glNormal3f( 0.0f,-1.0f, 0.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); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,
1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,
1.0f);
// Right face glNormal3f( 1.0f, 0.0f, 0.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);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,
1.0f);
// Left Face glNormal3f(-1.0f, 0.0f, 0.0f); 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(); //
xRot+=0.1f; glFlush(); glutSwapBuffers();
} void myTimeOut(int id) {
// X Axis Rotation
// called if timer event // ...advance the state of animation incrementally... Rot += 5.0f; glutPostRedisplay();
// request redisplay
glutTimerFunc(100, myTimeOut, 0);
// request next timer event
} void resize(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (GLdouble)width / (GLdouble)height, 1.0, 300.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }
Variabel global dibuat agar kita bisa mencoba-coba tiga macam mode fog. Pada void init() terdapat beberapa baris kode baru, yaitu:
•
glEnable(GL_FOG) yang melakukan inisialisasi fog
•
glFogi(GL_FOG_MODE, fogMode[fogfilter]); menentukan mode fog dengan variabel array fogMode. Variabel fogMode diinisialisasi dengan tiga nilai, yaitu GL_EXP, GL_EXP2, dan GL_LINEAR: •
GL_EXP – fog standar yang dirender pada keseluruhan screen. Efek fognya tidak terlalu terlihat namun jenis yang paling cepat dirender.
•
GL_EXP2 – fog jenis ini juga mirip dengan GL_EXP, hanya akan memberikan kesan dalam pada scene.
•
GL_LINEAR – pada fog jenis ini, efek fog diinterpolasi secara linier bergantung jarak dengan kamera sehingga didapat efek yang lebih baik.
•
glFogfv(GL_FOG_COLOR, fogcolor); menentukan warna dari fog.
•
glFogf(GL_FOG_DENSITY, 0.35f); menentukan seberapa padat kabutnya. Semakin tinggi nilainy, semakin pekat kabut yang dihasilkan.
•
Baris glHint (GL_FOG_HINT, GL_DONT_CARE); memberikan informasi kepada OpenGL tentang bagaimana proses rendering ingin dilakukan.
•
gl_dont_care – terserah openGL
•
gl_nicest – perhitungan fog dilakukan per-pixel.
•
gl_fastest – perhitungan fog dilakukan per-vertex yang berarti lebih cepat tapi lebih tidak akurat.
•
glFogf(GL_FOG_START, 1.0f); menentukan jarak dari kamera ketika fog mulai.
•
glFogf(GL_FOG_END, 5.0f); menentukan sejauh mana kabut masih berefek.
PERCOBAAN: Rubah berbagai variabel di atas untuk melihat apa pengaruhnya.