مثالی از نور پردازی

http://www.swiftless.com/tutorials/opengl/lighting.html

ثابت ها یی که در نور پردازی حتما باید فعال باشند.

    glEnable (GL_DEPTH_TEST);

    glEnable (GL_LIGHTING);

    glEnable (GL_LIGHT0)   ;                                                                                                برای تمام منبع ها  

    glEnable( GL_COLOR_MATERIAL );

GL_COLOR_MATERIAL

اگر ثابت فوق فعال نباشد شما نتیجه کارتان در نور پردازی را مشاهده نمیکنید.

glEnable( GL_COLOR_MATERIAL );

تابع glLightfv (نور پرادازی در Opengl )

از این تابع هم برای تعریف  مکان منبع نور و هم نوع آن  استفاده میشود.

پارامتر اول :  در اپن جی ال تعداد منابع نور محدود است پارامتر اول مشخص میکند که کدام منبع نور را در نظر 

دارین برای مثال : GL_LIGHT0 .

پارامتر دوم : میتواند ثابت موقعیت منبع نور  GL_POSITION و یا ثابت  نوع نور مثل  GL_DIFFUSE یا هر کدام

از انواع دیگر نور  را داشته باشد .

پارامتر سوم : پارامتر سوم  بسته به اینکه پارامتر دوم چه بوده تعریف میشود مثلا اگر  پارامتر دوم موقعیت بوده 

مختصات است واگر نور بوده رنگ نور منبع است RGBA  ،  که A شدت نور است .

    GLfloat specular[] = { 0.7, 0.7, 0.3, 1 };

   GLfloat lightpos[] = {1.5, 1.,- 1., 0.};

   glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

   glLightfv( GL_LIGHT0, GL_SPECULAR, specular );

نور پردازی در opengl


آشنایی با  انواع نور تعریف شده در opengl:

1-نور محیطی (Ambient): نوری که در محیط وجود دارد به طوری که جهت آن قابل تشخیص نیست.

2- نور انتشاری(Diffuse): فرض کنید منبع در بی نهایت قرار گرفته هنگامی که شی از نور این منبع روشن 

میشود نور انتشاری از خود باز تابش میکند.

3-نور آینه ای(Specular):از جهت خاصی تابیده شده است وتمایل دارد به جهت منبع تابیده شود که این ویژگی 

بیشتر برای فلزات است.


نور پردازی در opengl

نکته قابل توجه این است که نور پردازی برای محیط  سه بعدی تعریف شده است .

اما مشکل این جاست که اپن جی ال به طور پیش فرض عمق شکل در نور پردازی را متوجه نمیشود.

برای همین برای یک نور پردازی صحیح  باید در مقدار دهی اولیه  بافر عمق  هم باید تعریف شود.

glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB  |GLUT_DEPTH );

هم چنین باید انجایی که  دارین منابع نوریتان راتعریف میکنین این ویژگی را فعال کنید.

glEnable(GL_DEPTH_TEST);

در تابع Display هم باید بافر عمق را پاک کرد.

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 


تابع () glutPostRedisplay

از این تابع زمانی استفاده میشود که شما بخواهید داخل تابع دیگری تابع display تان را دوباره فراخوانی کنید.

اگر به کد  چرخش کره نگاه کنید اونجا استفاده شده.

کاربرد بافر دوگانه در opengl

تا الان که  فقط شکل ترسیم میکردین نیازی به دو بافر نداشتید .

اما  در متحرک سازی یا همون به اصطلاح پویا نمایی  این طور نیست .

تنها زمانی شما بهترین کارایی را دارین که بافر شما دو گانه باشد.  این طوری از پر پر زدن شکل جلو گیری میکنیم 

با تعویض بافر ها  اشیا ترسیم شده به نمایش در می آید.

یادتان به گوشه کتابهای درسیتون نیفتاد ؟؟! با ورق زدن سریع کتاب شکلتون متحرک میشد!

یک تکنیک

شاید شما نام و اسپل توابع را به خوبی یادتان نباشد اگر درحین نوشتن کلید ctrl+space را فشار دهید لیست توابع برایتان باز میشود.

sample code___ چرخش کره


#include

GLfloat angle=0.0;

void idle(void)

{

if(angle<360)

angle+=0.1;

else

angle=0.0;

glutPostRedisplay();

}

void winInit(void)

{

glClearColor(1.0,1.0,1.0,0.0);

}

void display(){

     glClear(GL_COLOR_BUFFER_BIT); 

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glPushMatrix();

glColor3f(1.1,0.0,1.0);

glRotated(angle,1.0,1.0,0.0);

glutWireSphere(0.9,50,50);

glEnd();

glPopMatrix();

glutSwapBuffers();

}

int main(int argc, char** argv){

glutInit(& argc,argv);

glutInitDisplayMode(GLUT_DOUBLE |GLUT_RGB);

glutInitWindowPosition(100,100);

glutInitWindowSize(400,400);

glutCreateWindow("simple");

winInit();

glutDisplayFunc(display);

glutIdleFunc(idle);

glutMainLoop();

return 0;

}


تابع glTranslatef یا glTranslated

کار این تابع هم انتقال است  ، یعنی جسم را از یک نقطه به نقطه دیگر انتقال میدهد.

تابع glScalef یا glScaled

این تابع هم بزرگنمایی  یا انقباض را دارد  .نسبت به هر کدام از محورها این نقباض یا کشیدگی را میتوان

 انجام داد. 

این تابع سه پارامتر دارد.

پارامتر اول کشیدگی(انقباض) حول محور x،

 پارامتر دوم کشیدگی(انقباض) حول محور y ، 

پارامتر سوم کشیدگی(انقباض) حول محور Z است.

اگر پارامتر ها بزرگتر از یک باشد بزرگنمایی داریم و اگر پارامترها کمتر از یک باشند انقباض را داریم . اگر هم 

از 1- استفاده کنید  قرینه شکل حول محور مربوطه را داریم .

تابع  glRotatef

 glRotatef(angle,x،y,z);

مقصود از x,y,z محورهای مختصات است .

کار این تابع دوران است . دوران حول یکی از محورهای مختصات .

کدام محور؟

هر کدام از محور ها را خواستید مقدار ان را یک کنید و بقیه را صفر کنید.


مثال:

void display() 

{

 glClear(GL_COLOR_BUFFER_BIT);

 glRotatef(66,0,0,1);

 glColor3f(2,2,0);   

 glutSolidTeapot(0.5);

 glFlush();

}

انواع متغییر ها در opengl

آپلود عکس

تابع glMatrixMode

تابع glMatrixMode یکی از ثابتهای زیر را به عنوان پارامتر دارد:


GL_MODELVIEW:


.برای انتقال وتغییر مکان ودوران و...استفاده میشود وحالت پیش فرض است


GL_PROJEXTION:

.برای حالت دو بعدی استفاده میشود

GL_TEXTURE:                                                                                      

 به جای این که شکل را رنگ کند از بافت تکسچر استفاده میکند.



تابع glFlush

فرض کنید در حال رسم شکلی در opengl  هستید. اگر انتهای کارتان اگر glFlush  را ننویسید هیچ خروجی را

 مشاهده نخواهید کرد.

چون اطلاعات داخل بافر است  و هنوز  روی صفحه نمایش اعمال نشده است ! بافر یک حافظه میانی است 

اگر شما  از یک بافر استفاده میکنید با نوشتن glFlush دستور انتقال اطلاعات از حافظه میانی(بافر) به صفحه

 نمایش را میدهید.

چگونه تعداد بافر را  مشخص کنیم؟

حتما تابع زیر را در main دیدین

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB)

GLUT_SINGLE  معرف تک بافره و GLUT_DOUBLE معرف دو بافر هستش

پس وقتی دستوری برای  اعمال روی صفحه داشتین مثل دستورا ت ترسیم شکل برای اعمال شدن نتیجه 

اگر  یک بافر داشتین از دستور ;()glFlush واگر دو بافر داشتین از دستور ;()glutSwapBuffers استفاده 

میکنیم.

تابع glutIdleFunc

این تابع   همون طور که اسمش روشه تابع ای است که در مواقعی بیکاری کار می کند .

برای مثال میخواهید در موقع بیکاری سیستم مکعب بچرخد. یا یک شکل حرکت کند از این تابع کمک میگرند.

منظور از بیکاری:

یعنی زمانی که شما هیچ تعاملی با کاربر نداشته اید .

در جواب دوست عزیزی که نظر گذاشته باید بگم که این تابع  در زمانی که با کاربر تعامل دارید کار نمیکند و در 

در حالتی که سیستم هیچ تعاملی ندارد و بیکار است فعالیت خودش رو از سر میگیرد .

مثال : فرض کنید کره در صفحه می چرخد و  کاربر هم میخواد راست کلیک کند تا با انتخاب یکی از گزینه ها 

منو  شکلی را رسم کند تا زمانی که راست کلیک را در صفحه میبیند و تعامل ادامه دارد Idle کار نمیکند.

بعد از انتخاب  و بسته شدن راست کلیک دوباره  زمان بیکاری سیستم شروع میشود.

حالا فرض کنید به جای اینکه از منو استفاده کنید از یکی از کلید های کیبورد استفاده کرده اید . خب 

چون زمان تعامل خیلی کوتاه است  در واقع سیستم  بیکار به نظر میرسد.


توابع opengl از نوع callback  هستند به چه معناست؟


اگر به همین چند تا تابعی که تا به حال گذاشتم دقت کنید می بینیدکه در واقع

یک تابع دارد تابع دیگری را فراخوانی میکند. در واقع پارامتر یک تابع ، تابع دیگری 

شده  به ا ین نوع توابع callback میگویند.در اپن جی ال هم تمام توابع از پیش 

تعریف شده اند و طریقه استفاده ما از طریق همین callback است.

مثلا همین توضیح تابع glutKeyboardFunc  را این طور مینویسند:

void glutKeyboardFunc(void(*func)(unsigned char key,int x,int y)

تابع glutKeyboardFunc

این تابع هم این گونه فراخوانی میشود:

;(اسم تابع)glutKeyboardFunc

فرضا:                                                                                                  ( glutKeyboardFunc( mykeyboard


تابع فراخوانی شده توسط این تابع سه پارامتر دارد:


void mykeyboard( unsigned char key, int x, int y)

پارامتر اول  حاوی کد اسکی کاراکتر فشار داده شده ی روی keyboard است.

(این تابع برای کاراکترهایی استفاده میشه که یک قسمتی هستند.

برای بعضی کلید های خاص  keyboard مثل F ها و کلید های پیمایش باید از تابع 

glutSpecialFunc استفاده بشه)

پارامتر دوم و سوم موقعیت موس را نگه میدارند.


ادامه مطلب به زودی

تابع glutMotionFunc

 glutMotionFunc برای زمانی است که یکی از دکمه های موس فشرده شود و

 هم زمان موس حرکت کند . در واقع با فرا خوانی این تابع به محض حرکت 

موس با  فشردن دکمه موس دستورات تابع اجرا میشود.

پس در ()main بنویسید :

(اسم تابع ) glutMotionFunc

فرض کنید که اسم تابع mouse است.

 این تابع دو پارامتر دارد :

void mouse  int x , int y )



نمونه کد:
glutMotionFunc(drawSquare);
///////////////////////////////
void drawSquare(int x, int y)
{
y = wh - y;
glColor3ub( (char) rand()%256, (char) rand()%256,
(char) rand()%256);
glBegin(GL_POLYGON);
glVertex2f(x+size, y+size);
glVertex2f(x-size, y+size);
glVertex2f(x-size, y-size);
glVertex2f(x+size, y-size);
glEnd();
glFlush();
}

تابع glutMouseFunc

برای این که بتوان تابع موس را فراخوانی کرد در ()main مینویسیم :

glutMouseFunc ( نام تابع );

برای مثال نام تابع را mouse میگذاریم  پس در ()main مینویسیم :

glutMouseFunc (mouse );

تابعی که اکنون تحت نام mouse نوشته میشود 4 پارامتر دارد :

void mouse( int button , int state , int x , int y )

پارامتر اول مشخص می کند که کدام دکمه ماوس فشرده شده یا رها می شود.که خود این پارامتر 3 حالت دارد:

GLUT_LEFT_BUTTON
GLUT_MIDDLE_BUTTON
GLUT_RIGHT_BUTTON

پارامتر دوم وضعیت دکمه ماوس را که فشردن یا رها شدن را مشخص می کند.که  این پارامتر 2 حالت دارد :
GLUT-DOWN 
GLUT-UP
  پارامتر سوم و چهارم هم مختصات موس به پیکسل هستند.

برای چک کردن این که کدام کلید زده شده از یک if استفاده می کنیم که مقادیر bottun , state را چک می کند.



نمونه کد:
void mouse(int button, int state, int x, int y)
{
switch (button)
{
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
  exit(0); 
}
}

تابع glViewport(پنجــــــــره دید)

شاید شما بخواهید اشکالی را که رسم کرده اید به سایز(اندازه)های مختلف در آورید . 

برای مثال  قبلا برنامه یک مثلث را نوشته اید . این برنامه خودش برای یک پنجره

 نمایش با مختصات و ویژگی های خودش بوده  اما ما  در برنامه جدیدمان میخواهیم

 از برنامه قبلیمان استفاده کنیم اما از سایز ومکان شکل در پنجره راضی نیستیم

 در واقع دیدمان به  پنجره عوض شده است. به عکس پرچم پاناما نگاه کنید . ابتدا

 تمام سایز پنجره را گرفته  اما بعد هم کوچکش کردم وهم مکانش را تغییر دادم. 

برای مثال:

void mydisplay(){

     glClear(GL_COLOR_BUFFER_BIT);

//glViewport(0,0,200,400);

     glBegin(GL_POLYGON);        

glVertex2f(-0.9,0.4);

glVertex2f(-0.5,0.8);

glVertex2f(-0.125,0.4);

glEnd();

glFlush();

}

اما الان می خواهید دید پنجره نمایش نسبت به این شکل تغییرکند مثلا مثلث به

 جای اینکه مثل این برنامه در ربع دوم با این سایز کشیده شود در مکان دیگری از

 صفحه نمایش با سایز دیگری کشیده شود.

نکته مهم 1 : برای گرفتن نتیجه تابع glviewport را قبل از glBegin بنویسید.

برای اینکارها از تابع glViewport استفاده میشود. شکل کلی تابع glViewport به

 صورت زیر است:

(طول شئ , عرض شئ , مختصات Y , مختصات glViewPort( X

نکته مهم 2 :این تابع بر حسب پیکسل است یعنی مختصات دهی بر حسب

 پیکسل میباشد.


این هم عکس برای فهم بیشتر ودرک کاربرد:


سایت آپلود عکس فیروز      سایت آپلود عکس فیروز


نکته مهم 3:مختصات (0،0 ) پنجره در اپن جی ال گوشه سمت چپ پایین

 صفحه است.  در حالی که خود پنجره نمایشی  مختصات دیگری برای

 صفر وصفرش دارد وآن گوشه سمت چپ بالای صفحه است.  

آپلود عکس و فایل


منو و زیر منو در opengl +مثال

طریقه ایجاد منو از طریق تابع:

int id=glutCreateMenu(mymenu);

تعریف ورودی های منو (منظور همون گزینه های منو است)

glutAddMenuEntry("نام گزینه",id);

تعریف زیر منو از طریق :

glutAddSubMenu("نام زیر منو",id);

در اخر هم منو رو با یکی از کلیدهای موس متصل میکنیم:

glutAttachMenu(GLUT_RIGHT_BUTTON);

توضیح پارامترها برام سخت بود که بنویسمشون یه مثال گذاشتم:

#include

int s=-1;

void display(void)

{

    glClear(GL_COLOR_BUFFER_BIT);

if(s==0)

{

glClearColor(1.0,0.0,1.0,1.0);   //pink

     glClear(GL_COLOR_BUFFER_BIT);  

}

if(s==1)

{

glClearColor(0.0,0.0,1.0,1.0);   //blue

     glClear(GL_COLOR_BUFFER_BIT);  

}

if(s==2)

{

glClearColor(1,0,0,1);         //red

glClear(GL_COLOR_BUFFER_BIT);

}

    glFlush();

}

void mymenu(int id)

{

if(id==1)

s=0;

   glutPostRedisplay();

}

if(id==2)

exit(0);

if(id==3)

{

s=1;

glutPostRedisplay();

    }

if(id==4)

s=2;

   glutPostRedisplay();

}


}


int main(int argc, char** argv)

   {

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

glutCreateWindow("Menu");

glutDisplayFunc(display);

////////////////////////////

int menu_ids=glutCreateMenu(mymenu);

glutAddMenuEntry("pink", 1);

glutAddMenuEntry("red",4);

glutAddMenuEntry("blue", 3);

int id_id=glutCreateMenu(mymenu);

glutAddSubMenu("COLORS",menu_ids);

glutAddMenuEntry("exit",2);


glutAttachMenu(GLUT_RIGHT_BUTTON);

////////////////////////////////////////////

    glutMainLoop();

return 0;

}


کتابخانه  OpenGl  برای ++C

کتابخانه glut.h را از اینجـــــــا دانلود کنـید.

قوانین نوشتاری در opengl

1-دستورات opengl با پیشوند gl آغاز میشوند.

 opengl از کتابخونه های زیادی تشکیل شده که دو کتابخونه ی مهمش GLU و

 GLUT هستند.

 از مشخصه های توابعی که در این دو کتابخونه وجود دارد دارد این است که با

 GLU یا GLUT شروع میشنوند.درواقع پیشوند تابع معرف کتابخانه آن نیز هست.

2- ثابتها هم کلا با حروف بزرگ نوشته میشوند وپیشوند _GL را دارند.


طریقه اضافه کردن کتابخانه Open Gl در ++c

آموزش اضافه کردن کتابخانه OpenGl  را از اینجا یاد بگیرید.

Opengl چیست؟

به نام خدا

opengl یک نرم افزار نیست یک زبان برنامه نویسی هم نیست یک Application Programming Interface  است .

API یعنی رابط نرم افزاری

اما خیلی ها به اشتباه انرا یک زبان برنامه نویسی خطاب میکنند . 

opengl  مخفف عبارت  (open Graphic Library) است . پس کافیست

 کتابخانه opengl را به مجموعه کتابخانه هر زبانی که بلد هستید اضافه کنید .


 یکی از قابلیت های خوب opengl این است که کنار اکثر زبان برنامه نویسی استفاده 

میشود و به یک زبان برنامه نویسی بستگی ندارد .

چون نسبت به گزینه های دیگر گرافیک  برای بازی ها سبک محسوب میشود میتواند یک

گزینه مناسب برای برنامه نویسان بازی  موبایل باشد .

یکی از قابلیت های خوب دیگر opengl این است که در هرسیستم عاملی استفاده میشود 
و شما را محدود نمیکند  .

 
یکی از بازیهایی که گرافیک ان توسط opengl طراحی شده است همان angry bird معروف  هستش .