Saturday, August 22, 2009

OpenGL rendering basics....

Game program ေတြ၊ ဒါမွ မဟုတ္ graphic rendering program ေတြ ရဲ႕ အဓိက အလုပ္လုပ္တဲ့ ပံုစံက real-time rendering လို႔ ေျပာလို႔ရ ပါတယ္။ သူတို႔က ပံုမွန္ database, windows application ေတြနဲ႔ အလုပ္လုပ္တဲ့ ပံုစံ မတူပါဘူး။
Windows form application တစ္ခုကို event-driven program လို႔ ေျပာလို႔ ရမယ္ထင္ပါတယ္။ သူတို႔က user input ကို ေစာင့္ေနတယ္။ User က တစ္ခုခု input ေပးလိုက္မွ ေနာက္ဆက္ လုပ္ရမယ့္ ကိစၥကို ဆက္လုပ္တယ္ေလ။ ဥပမာ- Personal data ေတြ ျဖည့္တဲ့ application form တစ္ခု လိုေပါ့။ User က ျဖည့္စရာ ရိွတာ ျဖည့္ၿပီး button ကို ႏွိပ္လိုက္မွ က်န္တာ ဆက္လုပ္တာမ်ိဳးေပါ့။
Game ေတြ၊ animation တစ္ခုကို rendering လုပ္ေနတဲ့ program ေတြမွာ က်ေတာ့ အဲလို မဟုတ္ပါဘူး။ သူတို႔က infinite loop တစ္ခုပါ။ Program ကို စလိုက္ၿပီ ဆိုကထဲက user input ရိွရိွ၊ မရိွရိွ game logic ေတြ၊ AI ေတြ၊ graphic လႈပ္ရွားမႈေတြက ေနာက္ကေန လုပ္ေနရပါတယ္။ ခ်ိန္သားကိုက္ကိုက္ လည္း ျဖစ္ရပါတယ္။ User input ရိွခဲ့ရင္လည္း အဲဒီ input အေပၚ မူတည္ၿပီး logic ကို ေျပာင္းေပးရတယ္။ လိုအပ္ရင္ graphic ဆြဲတာ ေတြကို update လုပ္ေပးရပါတယ္။ User က ဘာမွ မလုပ္ပဲ ေနရင္လည္း game logic နဲ႔ လုပ္စရာရိွတာ ေတြက ေနာက္ကေန လုပ္ေနရပါတယ္။ အဲဒီလိုပဲ graphic rendering ေတြကလည္း update လုပ္ေပးေနရတယ္ေလ။ ဒါေၾကာင့္ သူတို႔က rendering ကို အၿမဲ လုပ္ေနရပါတယ္။
Main game loop က user input ရိွသည္ျဖစ္ေစ၊ မရိွသည္ ျဖစ္ေစ၊ အၿမဲ လုပ္ေနပါတယ္။ User က game ထဲကေန exit လုပ္ေတာ့မယ္လို႔ singal ေပးလိုက္မွသာ အဲဒီ loop က ထြက္သြားပါတယ္။ ဒါေၾကာင့္ game loop ေတြမွာ ဘယ္အခ်ိန္ ၿပီးမယ္ ဆိုတဲ့ ကန္႕သတ္ခ်က္ မရိွပါဘူး။ User input အေပၚမွာပဲ ျဖစ္ျဖစ္၊ ဒါမွမဟုတ္ game ရဲ႕ အေျခအေန (state) တစ္ခု အေပၚမွာပဲ ျဖစ္ျဖစ္ မူတည္ၿပီး ထြက္သြားတာမ်ိဳးပဲ ျဖစ္ႏိုင္ပါတယ္။
အဲဒီလိုပါပဲ။ ကၽြန္ေတာ္တို႔ OpenGL graphic rendering application တစ္ခုကို ေရးမယ္ ဆိုရင္လည္း သူက rendering loop တစ္ခုပါ။ အဲဒီ loop ထဲမွာ user input ကို detect လုပ္တဲ့ ကိစၥေတြပါတယ္။ Drawing ကို ဆြဲတဲ့ ကိစၥေတြ ပါတယ္။ လိုအပ္ရင္ ကၽြန္ေတာ္တို႔က ကိုယ္ပိုင္ logic ေတြ ထပ္ထည့္ၿပီးေတာ့ အဲဒီ loop ထဲမွာ အလုပ္လုပ္ခုိင္းလို႔ ရပါတယ္။ ဒါေၾကာင့္ OpenGL program တစ္ခုကို ဖန္တီးတယ္ ဆိုရင္ အဲဒီ program က ဖန္တီးတဲ့ graphic ပံုေတြက အေသျဖစ္ေနတယ္ ဆိုရင္ေတာင္မွ အဲဒီ program loop က အၿမဲ ပတ္ေနၿပီး အလုပ္လုပ္ေနတယ္ ဆုိတာ သိထားဖို႔ လိုပါတယ္။
OpenGL program တစ္ခုကို ဖန္တီးဖို႔ အတြက္ GLUT (OpenGL Utility Toolkit) ကို သံုးမယ္ ဆိုရင္လည္း ကၽြန္ေတာ္တို႔ရဲ႕ main function ထဲမွာ အဲဒီ loop န႔ ဲ ပါတ္သက္တာေတြကို ေတြ႕ႏိုင္ပါတယ္။ ေအာက္မွာ နမူနာ ျပထားတာကို ၾကည့္ၾကည့္ပါ..။

int main(int argc, char **argv)
{
// normal initialisation

glutInit(&argc, argv);
// use double buffer to get better results on animation

// use depth buffer for hidden surface removal

glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(600,600);
glutInitWindowPosition(100,100);

win = glutCreateWindow("OpenGL assignment 1");
// set the clearcolor

glClearColor(0.6,0.6,0.6,0.0);


// Here, you can initialize your customized things…


// register your callback functions
glutDisplayFunc(myDisp);

glutMouseFunc(myMouse);
glutMotionFunc(myMotion);

glutKeyboardFunc(myKeys);

glutReshapeFunc(reShape);


// enter the main loop
glutMainLoop();


//Program finish
return 1;

}


အေပၚမွာ ျပထားတာက အရိုးရွင္းဆံုး GLUT code ေလးတစ္ခုပါ။ အဲဒီ code ထဲမွာ callback functions ေတြ ကို ေတြ႕ႏိုင္ပါတယ္။ Callback functions ေတြ ဆိုတာ main loop ကေန အလိုအေလွ်ာက္ လွမ္းေခၚေပးတဲ့ function ေတြပါ။ အခု ကၽြန္ေတာ္တို႔က GLUT ကို သံုးၿပီး ေရးေနတယ္ဆိုေတာ့ GLUT ကေန လိုအပ္ရင္ လွမ္းေခၚ ေပးမွာေပါ့ေနာ္။
အဲဒီ code ထဲမွာ myDisp, myMouse, myMotion, myKeys, reShape ဆိုတဲ့ function ေတြက ကၽြန္ေတာ္တို႔ ရဲ႕ ကိုယ္ပိုင္ ဖန္တီးထားတဲ့ function ေလးေတြပါ။ အဲဒီ function ေလးေတြ ထဲမွာ ကၽြန္ေတာ္တို႔ ၾကိဳက္တာ၊ လုပ္ခ်င္တာကို ေရးထား လို႔ရတယ္ေလ။ ကၽြန္ေတာ္တို႔က GLUT ကို ဘယ္ကိစၥမွာ ဘယ္ function ကို လုပ္ရမယ္ ဆိုတာ ေျပာေပးဖို႔ပဲ လိုပါတယ္။ ဒါကို ကၽြန္ေတာ္တုိ႔ function ေလးေတြကို GLUT နဲ႔ register လုပ္တယ္ လို႔ ေခၚပါတယ္။
ကၽြန္ေတာ္တို႔ ရဲ႕ function ေလးေတြကို GLUT ကို register လုပ္ၿပီးၿပီ ဆိုရင္ main loop ကို ေခၚလိုက္ ရုံပါပဲ။ ဒါဆို GLUT ကေန OpenGL အတြက္ main loop ကို စအလုပ္လုပ္ ၿပီေပါ့။ glutMainLoop ( ) ဆိုတဲ့ function ေလးကို ေတြ႕တယ္ မဟုတ္လား။ ဒါက main rendering loop ကို စဖို႔ ေျပာလိုက္တာပဲေလ။ ဒါဆို main loop က program မထြက္မခ်င္း run ေနမယ္။ ၿပီးေတာ့ ကၽြန္ေတာ္တို႔ register လုပ္ထားတဲ့ callback function ေလးေတြကို လိုအပ္သလို ေခၚေခၚလုပ္သြားပါလိမ့္မယ္။
ကၽြန္ေတာ္တို႔က ကၽြန္ေတာ္တို႔ လုပ္ခ်င္တာေတြကို register လုပ္ထားတဲ့ callback function ေလးေတြထဲမွာ ေရးထား လိုက္ရံုပဲေပါ့။
ဥပမာ- myDisp ဆိုတဲ့ function ေလးက rendering function လို႔ ေျပာလို႔ရတယ္။ Main loop ကေန အၿမဲတမ္း အဲဒီ function ကို ေခၚေနမွာေပါ့။ ကၽြန္ေတာ္တို႕က ဆြဲခ်င္တာေတြကို အဲဒီ function ထဲမွာ ေျပာထားရင္ ရပါတယ္ေလ။ myMouse function က user ဆီကေန Mouse input တစ္ခုခု ၀င္လာရင္ ဘာလုပ္ရမယ္ ဆိုတာ ေျပာေပးထားတာေပါ့။ myKeys က keyboard input ေတြကို handle လုပ္ဖို႔ပါ။ ဒါဆို အေပၚက callback functions ေလးေတြနဲ႔ main loop အေၾကာင္းကို သေဘာတရား နားလည္ ႏိုင္မယ္ ထင္ပါတယ္။

0 comments:

Post a Comment