# مباحث متفرقه برنامه نویسی > طراحی و ساخت بازی‌های کامپیوتری >  نمونه تصاویر زیبا از کار با opengl در زمینه طراحی بازی

## complexcoding

نمونه کارهای زیبا با opengl در زمینه طراحی بازی

057.jpg
041.jpg
wire_02.jpg
raptor_901_advanced_viewport_050915.jpg

----------


## complexcoding

گرافيك كامپيوتري 

مقدمه: 

امروزه قابليت هاي سمعي و بصري بخش عمده اي از علم چند رسانه اي را  تشكيل مي دهند و جزء لاينفك فن آوري هايي شده اند كه زندگي قرن بيست و يكم  را تعريف مي كنند. بي شك خلق سخت افزار هاي ديجيتال كه قابليت عملكرد با  سرعت هاي بسيار زياد را دارند اساس اين فن آوري ها بوده است؛ اما ورود  مفهوم رنگ به دنياي ديجيتال چنان تحولي در اين عرصه به وجود آورد كه نه  تنها رشته هاي جديدي از علم را  پيش روي انسان گشود، بلكه منجربه تغيير جهت  پيشرفت بسياري از علوم ديگر گرديد. از رياضيات، هندسه تحليلي براي خلق  دنياهاي مجازي به كار گرفته شده و از الكترونيك براي افزايش امكانات و  قابليت هاي گرافيكي استفاده شد. علم نرم افزار و هنر برنامه نويسي كه تا  چندي قبل در طراحي سيستم هاي عامل و پياده سازي هوش مصنوعي به حد اعلاي خود  مي رسيد، با مفهوم جديدي به نام واقعيت مجازي و شبيه سازي دنياي واقعي  مواجه شده. هزاران مفهوم جديد در پي مفهوم گرافيك و تصاوير ديجيتال بوجود  آمد وهزاران نفر در گوشه و كنار دنيا سرگرم فعاليت و مطالعه در اين زمينه  ها شدند. 
وجود هزاران نرم افزار وابسطه به قابليت گرافيكي كامپيوتر، وجود سيستم  هاي چند رسانه اي از جمله ماهواره ها و تلوزيون هاي مدرن و به اوج رسيدن  غول نرم افزار دنيا ، مايكروسافت ، از طريق  به كار گيري گرافيك در سيستم  هاي عامل خانواده Windows، اهميت آشنايي با مفهوم گرافيك در كامپيوتر را  واضح مي كند. 
بيش از اين، اگر شما به نحوه ي خلق دنياي مجازي كه گرافيك كامپيوتري و  بخصوص گرافيك سه بعدي عنصر اصلي آن مي باشدعلاقمند هستيد، بايد پا را فراتر  گذاشته و جنبه هاي مختلفي از علم نرم افزار را مطالعه كنيد. 
در اين سري از مقالات، تصميم داريم تا با يكي از مهمترين ابزارهايي كه  در اختيار برنامه نويسان بازي هاي ويدئويي و كامپيوتري است آشنا شويم. اين  ابزار با نام OpenGL شناخته مي شود و فن آوري بسيار انعطاف پذير و در عين  حال پيچيده اي است كه به برنامه نويسان اجازه مي دهد تا فضاهاي سه بعدي را  از طريق هنر برنامه نويسي و با در اختيار داشتن سخت افزار مناسب خلق كنند و  به تصوير بكشند. 
همانطور كه شايد بدانيد، فن اوري هاي مشابهي براي دست يافتن به اين هدف  وجود دارند كه معرفي آنها و مقايسه OpenGL با هر كدام را به بخش هاي آينده  موكول خواهيم كرد. 
در مقاله اول و پيش از آنكه وارد جزئيات فن آوري ذكر شده شويم، لازم است تا با برخي موضوعات مقدماتي و چند اصطلاح مهم آشنا شويم. 

مفهوم گرافيك كامپيوتري: 

مهمترين ابزار خروجي كه مي تواند به مفهوم گرافيك كامپيوتري عينيت  ببخشد، صفحه نمايش (Monitor) است كه امروزه با روشهاي متفاوت در اندازه ها و  كيفيت هاي مختلفي توليد مي شوند. مشخصه اندازه در مورد يك صفحه نمايش به  طول قطر اين ابزار اشاره ميكند و اندازه ها معمولا بين 14 تا 21 اينچ  هستند.براي مفهوم كيفيت نيز مي توان تعاريف مختلفي را بيان كرد اما اين  مفهوم بيش از هر چيزي به وضوح تصوير اشاره مي كند كه صفحه نمايش مي تواند  توليد كند. 
در معماري سخت افزار هاي گرافيك امروزي (و كارت هاي گرافيكي در راس  آنها) تصاوير به صورت مجموعه اي از نقاط در نظر گرفته مي شوند. هر نقطه رنگ  و مشخصات خاص خود را دارد و كوچكترين جزئي محسوب مي شود كه يك تصوير را  تشكيل مي دهد. به اين نقاط در اصطلاح پيكسل (Pixel=Picture Element ) اطلاق  مي شود. به مجموعه ي پيكسل هايي كه در هر لحظه از طريق ابزارهايي مانند  صفحه نمايش ترسيم مي شود صفحه تصوير (Screen) گفته مي شود. 
مفهوم گرافيك و خروجي تصوير در يك سيستم ديجيتال مانند كامپيوتر هاي  شخصي و به كمك ابزاري مانند صفحه نمايش ، نقش بستن تصاوير دلخواه بر روي  صفحه تصوير است. 
صفحه تصوير دو بعدي در نظر گرفته مي شود و معمولا پيكسل هايي كه در اين  دو بعد وجود دارند از طريق مختصات آنها قابل دسترسي مي باشند. به شكل زير  توجه كنيد: 

همانطور كه در شكل بالا نيز به آن اشاره شده، مبداء مختصات دو بعدي بر  روي صفحه ي تصوير، گوشه ي بالاي سمت چپ در نظر گرفته مي شود. مختص افقي  مختص x ها و مختص عمودي مختص y ها ناميده مي شود. اولين پيكسل قابل نمايش  بر روي صفحه تصوير با مختص (0‚0) شناخته مي شود. احتمالا مختصات آخرين عنصر  در گوشه ي پايين سمت راست نيز براي شما اهميت دارد. اين مختصات معادل (  Mx-1 , MY-1 ) است كه Mx وMy در آن  مشخص كننده تعداد پيكسل هايي هستند كه  به ترتيب در مختص x وy نمايش داده مي شوند. 
اينكه در هر لحظه Mx وMy مي توانند چه اعدادي را مشخص كنند به توانايي  هاي سخت افزار هاي گرافيكي (كارت گرافيك )، سيستم عامل و بخش هاي ديگر سخت  افزار مورد استفاده بستگي دارد. 
واضح است كه مقدار Mx*My مشخص كننده تعداد پيكسل هايي است كه در صفحه  تصوير نمايش داده مي شود. ابعاد صفحه تصوير كه بصورت Mx*My بيان مي شود  معمولا ابعاد استانداردي هستند كه برخي از آنها را در زير مشاهده مي كنيد: 
200*320 
480*640 
600*800 
و... 
علاوه بر ابعاد، مشخصات ديگري نيز وجود دارند كه صفحه تصوير را تشكيل  مي دهند. اين مشخصات، اگرچه در ميان  كليه پيكسل ها مشتركند، اما برخلاف  ابعاد به شرايط تك تك  پيكسل ها اشاره مي كنند. مهمترين اين مشخصات، مشخصه  رنگ مي باشد. مشخصه رنگ در هر حالت خاص از صفحه نمايش، مشخص مي كند كه هر  پيكسل مي تواند چه تعداد و چه رنگهايي را داشته باشد. مثلا اگر در يك حالت  بخصوص صفحه تصوير در ابعاد 200*320 تنظيم  شده باشد و مشخصه رنگ صفحه تصوير  در حالت ”4 بيت“  قرا ر گرفته باشد، مفهومش آنست كه در اين حالت ، صفحه  تصوير شامل 320 پيكسل در مختص x (از 0 تا 319 ) و 200 پيكسل در مختص y (از 0  تا 199)  است كه هر يك از پيكسل ها مي توانند 16=4^2 رنگ متفاوت داشته  باشند. 
اين بدان معني است كه هر پيكسل در هر لحظه ميتواند رنگي معادل شماره ي  صفر الي 15=1-4^2 داشته باشد. حال اينكه هر شماره (15-0) چه رنگي را مشخص  مي كند بستگي به شرايط سخت افزار و نرم افزار در آن لحظه دارد. البته اين  شرايط كاملا تعريف شده است و براي يك بر نامه نويس متوسط كاملا قابل درك مي  باشد. 
از آنجايي كه صفحه ي تصوير، در دو بعد در نظر گرفته ميشود، مي توان  مشخصه رنگ را بعد سوم صفحه در نظر گرفت. از اين رو معمولا به آن عمق رنگ  (Color Depth) گفته مي شود. 
 به حالت هاي متفاوتي كه صفحه تصوير مي تواند داشته باشد و با مشخصات  تشريح شده (ابعاد و عمق رنگ ) تعريف مي شود اصطلاحا وضوح تصوير (  Resolution ) اطلاق مي شود. 
همانطور كه احتمالا متوجه شده ايد، توانايي استفاده ازحالت خاصي از  صفحه تصويروابسطه به امكانات و قابليت هاي سخت افزاري و نرم افزاري سيستم  مورد استفاده است. به عنوان مثال براي آنكه بتوانيم صفحه تصويري با ابعاد  600*800 و عمق رنگ ”16 بيت “ ( كه به صورت 16*600*800 نمايش داده مي شود)  را استفاده كنيم، بايد اولا از نظر سخت افزاري حافظه اي شامل بيش از  800*600*2=? بايت در اختيار داشته و ثانيا از نظر نرم افزار ي، امكان  دستيابي به و تغيير هر نقطه اي از اين حافظه را با سرعت مناسب را داشته  باشيم. 
همانطور كه قبلا گفته شد، مفهوم گرافيك و خروجي تصوير به بيان بسيار  ساده در يك سيستم ديجيتال مانند كامپيوترهاي شخصي و به كمك ابزاري مانند  صفحه نمايش ، نقش بستن تصاوير دلخواه بر روي صفحه تصوير است. اين بيان ساده  را مي توان با مثالي ساده به صورتي كه در ادامه مي خوانيم بيان كرد. فرض  كنيد بتوان نقاطي را برروي صفحه تصوير مشخص كرد كه مختصات آنها حدودا با  توابع رياضي زير برابر باشد: 


F(x,y): 
X= X0 + R * Cos(t) 
Y= Y0 + R * Sin(t) 

شكل هندسي اين تابع بر روي صفحه ي دو بعدي x-y يك دايره را مشخص مي  كند. بنابراين،  فرض بالا منجر به مشخص شدن يك دايره يا بخشي از يك دايره  با شعاع R و به مركزX0 و Y0 بر روي صفحه تصوير مي شود.  

گرافيك دوبعدي و كاربرد هاي آن: 

تصاوير در يك سيستم ديجيتال مانند كامپيوترهاي شخصي نيز بر اساس تعاريف  ارائه شده در قسمت هاي قبلي تعريف، ذخيره و بازيابي مي شوند. به دليل  شرايط خاصي كه در نرم افزار ها و سخت افزار هاي امروزي وجود دارد، تصاوير  معمولا به صورت مجموعه اي از پيكسل هايي تعريف مي شوند كه در كنار يكديگر  شكل مستطيل به خود مي گيرند. 
مثلا يك دايره بايد در مجموعه اي مستطيلي شكل از پيكسل ها رسم شود  وبراي متمايز كردن بخش اصلي (شكل دايره) در كل تصوير (به شكل مستطيل) از يك  رنگ خاص (مثلا رنگ مشكي به عنوان رنگ پس زمينه (Background ) استفاده كرد.  اين مثال را در شكل زير مي بينيم: 

شايد نياز باشد براي بدست آوردن شكل اصلي به كمك تعدادي دستورالعمل رنگ  پس زمينه را از تصوير حذف كرد. اين عمل كه در آن با حذف كردن بخش هايي از  يك تصوير، شكل دلخواه را به صورت خالص و جدا از قالب مستطيلي شكل بدست مي  آوريم، عمل شفاف كردن تصوير ( Transparent ) ناميده مي شود و كاربرد هاي  بسياري دارد. به عنوان مثال، مي توانيد با شفاف كردن پنح نسخه از تصوير  بالا (يعني حذف كردن رنگ زمينه وبدست آوردن شكل دايره خالص ) و سپس كنار هم  قرار دادن اين پنج دايره برروي يك زمينه جديد و دلخواه ، نماد مسابقات  المپيك را ترسيم كنيد: 
به تصاويري كه به شكل مسطتيل ذخيره مي شوند و ذخيره سازي آنها براساس  پيكسل ها مي باشد، تصاوير نقش بيتي (Bitmap) گفته مي شود كه پركاربرد ترين  قالب هاي تصويري هستند. قالب هاي .bmp و .dbi و .pcx از معروف ترين قالب  هايي هستند كه تصاوير در آنها به همين صورت ذخيره مي شوند. 
مشخصاتي كه در قالب هاي تصويري براي بازيابي تصاوير تعريف مي شوند  علاوه بر ابعاد و عمق رنگ تصوير، گاهي شامل مفاهيم پيشرفته تري نيز مي  باشند. به عنوان نمونه مشخصه آلفا مفهومي معادل ”مقدار شفافيت“ را تعريف مي  كند كه مي توان بااستفاده از آن مشخص كرد در صورت ترسيم شدن تصوير فعلي بر  روي يك پس زمينه، چه مقدار از رنگ پس زمينه از تصوير فعلي عبور كند (مانند  عبور نور از شيشه). اين مفهوم در واقع به نوعي تركيب كردن تصوير زمينه با  تصوير فعلي است و تركيب  آلفا (Alpha Blending) ناميده مي شود. براي پياده  سازي اين مفهوم در يك قالب تصويري علاوه بر عمق رنگ و ديگر مشخصات، تعدادي  بيت براي هر پيكسل در نظر گرفته مي شود كه مخصوص به مقدار آلفا يا مقدار  شفافيت پيكسل ها مي باشد. 
از آنجا كه قالب تصاوير استفاده شده در هر سيستم، تاثيرات بسياري از  جمله سرعت و دقت بر روي عملكرد سيستم دارد، انتخاب قالب مناسب اهميت زيادي  دارد. قالب هايي كه عمق رنگ بيشتري (24 يا 32 بيت بر پيكسل ) ارائه مي دهند  كيفيت بيشتري دارند اما از آنجا كه حافظه و پردازش بيشتري براي استفاده از  آنها مورد نياز است ، از سرعت و كارايي سيستم مي كاهند. قالب هايي كه عمق  رنگ كمتر (8 يا 16 بيت بر پيكسل) ارائه مي دهند، با كاهش كيفيت تصوير و در  مقابل آن افزايش سرعت و كارايي سيستم همراه هستند. مثلا در سيستم هاي  بلادرنگ كه سرعت بالايي مورد نياز است، معمولا از قالب هاي 8 بيتي استفاده  مي شود. اين قالب ها تصوير را با حداكثر 256=8^2 رنگ تعريف مي كنند. 
در حالت 256 رنگ ، جدولي شامل 256 كد كه هر كدام مشخص كننده يك رنگ مي  باشد، به عنوان جدول رنگ در نظر گرفته مي شود. هر محل از جدول (0 الي 255)  مي تواند شامل عددي 16 بيتي (يا بزرگتر ) باشد ودر واقع رنگي معادل رنگ هاي  حالت 16 بيتي (يا بيشتر) را نگهداري كند. با استفاده از اين جدول كه تعداد  256 رنگ را نگهداري مي كند ، ميتوان تصويري را بوجود آورد كه در آن ، رنگ  هر پيكسل با شماره اي بين 0 الي 255 مشخص شده است. براي بدست آوردن رنگ  واقعي پيكسل ها، ابتدا به محلي از جدول كه بايت رنگ در هر پيكسل به آن  اشاره مي كند، مراجعه مي شود و رنگ واقعي پيكسل از آن محل بدست مي آيد. به  شكل زير توجه كنيد: 

همانطور كه مي بينيد محل از جدول رنگ شامل يك رنگ واقعي است و براي  بدست آوردن رنگ واقعي هرپيكسل به اين جدول مراجعه مي شود.مثلا محل (0،0) در  نمونهي بالا رنگي معادل محل 1 جدول دارد.پس رنگ اين پيكسل ،همانطور كه در  محل 1 جدول ثبت شده ، قرمز است. 
به جداول رنگ كه در بالا توضيح داده شد اصطلاحا پالت (Palette) گفته مي  شود. هر محل از يك پالت يك ورودي پالت (Palette-Entery) معمولا قالب هايي  كه عمق رنگ 8 بيت (با 256 ورودي پالت) را ارائه مي دهند، قالب هايي تصويري  با رنگ شماره گذاري شده (Index Color Image Formats) ناميده مي شوند. 
مفاهيم اوليه قالب هاي تصويري را به صورت بسيار خلاصه در بالا مرور  كرديم . اين قالب ها هميشه شامل تصاوير دو بعدي مي باشند و كاربرد هاي  زيادي در سيستم هاي گرافيكي دو بعدي يا گرافيك سه بعدي دارند. از كاربرد  هاي آنها در كنار فن آوري OpenGL كه براي خلق دنياهاي مجازي سه بعدي طراحي  شده است، مي توان به طرح هاي (Textures)،قلم ها (Fonts) و در برخي موارد  جلوه هاي ويژه بصري (Visual Effects) اشاره كرد. 

طرح هها يا Textureها به تصاويري گفته مي شود كه برروي سطوح (Surfaces)  اشياء قرار گرفته و به واقعي تر جلوه كردن اشياء كمك مي كنند. مثلا اگر  ميزي را كه ا زچوب ساخته شده است را شبيه سازي كنيم پس از طراحي آن (به  صورت سه بعدي )، تصويري كه شامل طرح چوب مورد نظر ما است را بر روي سطوح  اين ميز مي كشيم تا ميز از جنس چوب به نظر آيد. در اين مثال، طرح چوب كه از  طريق يك تصوير بدست آوريم در اصطلاح طرح (Texture) ناميده مي شود. 
به عنوان نمونه ا ي ديگر به اين موضوع اشاره مي كنيم كه در معماري فن  آوري  OpenGLجايي براي استفاده از قلم هاي (Fonts) استاندارد سيستم عاملي  مانند ويندوز در نظر گرفته نشده (دلايل آن را بعدا مطالعه خواهيم كرد) و  براي آنكه بتوانيم متني را به كمك OpenGL برروي صفحه تصوير به نمايش  درآوريم بايد از تصاويري كه شامل حروف و علائم هستند استفاده كنيم. 
جلوه هاي ويژه بصري (Visual Effect) نيز به تاثيراتي گفته مي شود كه  جلوه بخصوصي را در تصاوير بوجود مي آورند. مثلا تاثير نور خورشيد برروي لنز  دوربين كه براي شبيه سازي آن معمولا از تصاوير به همراه تكنيك تركيب آلفا  (Alpha Blending) استفاده مي شود. البته روشهاي گوناگوني براي توليد جلوه  ها ي ويژه وجود دارد. 


مطالبي كه تا اينجا بررسي كرديم، شامل مفاهيم اوليه گرافيك دوبعدي در  سيستم هاي ديجيتال امروزي بود.مفاهيم پيشرفته تري در اين رابطه و بخصوص در  رابطه با گرافيك سه بعدي را در مقالات بعدي مطالعه خواهيم كرد و پس از آن  در هفته هاي آينده به سراغ معرفي فن آوري هاي موجود در دنياي گرافيك  كامپيوتري مي رويم تا موقعيت OpenGL را دقيقا درك كنيم. بادرك موقعيت  OpenGL مي توانيم به راحتي آن را آموخته و به درستي از آن استفاده كنيم.                                                                                          

گرافیک کامپیوتری همواره از جمله  جذابترین جنبه های کامپیوترها بوده است. بازیها، برنامه های طراحی گرافیکی  دو بعدی و سه بعدی و شبیه سازیها همگی به نوعی از قابلیتهای گرافیکی یک  کامپیوتر بهره میبرند. مهمترین نکته در این زمینه، برقراری تعادلی منطقی  بین کیفیت تصاویر نمایش داده شده بر روی صحنه و سرعت اجرای برنامه میباشد.  یکی از راه هایی که در دو دهه اخیر همواره برای افزایش سرعت مورد استفاده  قرار گرفته است، حذف موانع غیرضروری بوده است. در این راه، سعی شده است تا  ارتباط برنامه نویس به ساده ترین صورت با سخت افزار گرافیکی برقرار شود. 
تقریبا همزمان با عرضه اولین نسخه های ویندوز، محصولاتی نظیر Glide و  WinG هم به بازار آمدند که کم و بیش از حمایت مایکروسافت هم برخوردار  بودند. ولیکن به جرات می توان گفت شرکت Silicon Graphics اولین محصول  استاندارد و همه منظوره را برای پیاده سازی گرافیک در سیستمهای ویندوز  ارائه نمود. محصول این شرکت که OpenGL نام دارد، در طی حدود یک دهه، علی  رغم ضعفهای فراوان توانسته است به حیات خود ادامه دهد. (بد نیست بدانید که  OpenGL از روی بسته نرم افزاری بنام Iris GL ساخته شد. این کتابخانه در دهه  80 در سیستمهای UNIX کاربرد فراوانی داشت.) شاید این مسئله بیش از هر چیز  دیگری به سادگی OpenGL مربوط شود. این سادگی به حدی است که میتوان گفت  OpenGL کتابخانه استاندارد صنعتی گرافیک میباشد. امروزه با عرضه نسخه های  جدید DirectX، شاید حداقل در صنعت ساخت بازی کمتر به OpenGL توجه شود ولی  این کتابخانه هنوز هم علاقمندان خاص خود را دارا میباشد  و اکثر نرم  افزارهای کاربردی طراحی همچون برنامه های CAD/CAM، انیمیشن یا ویرایش تصویر  بطور پیش فرض از آن بهره میبرند. در این مقاله سعی خواهیم کرد با هم نگاهی  هر چند گذرا به ویژگیها و نقاط ضعف این مجموعه بیاندازیم. 
اگر بخواهیم از دید مهندسی نرم افزار به OpenGL نگاه کنیم، شاید سه  خصوصیت بارز برای آن بیابیم. OpenGL به شیوه ای طراحی شده است که دستورات  در یک محل صادر شده و در محل دیگر اجرا شوند، به همین سادگی. به این  معماری، ساختار مشتری/خدمات دهنده (client/server) گفته میشود. بدین شیوه  OpenGL میتواند حتی بر روی شبکه های کامپیوتری هم بخوبی کار کند. خصوصیت  دیگر استفاده از یک محل مجتمع برای نمایش تصاویر میباشد. این محل که  میتواند در هر جایی از حافظه قرار بگیرد (از جمله حافظه گرافیکی) بافر فریم  (frame buffer) نامیده میشود. مورد آخر اینکه OpenGL معمولا خیلی در مورد  محدوده پارامترها وسواس به خرج میدهد و اجازه نمیدهد مقادیر خارج از حوزه  ارسال شوند. این عمل که parameter validation نام دارد گاهی اوقات باعث  پایین آمدن سرعت رندر میگردد. 
شاید خصوصیت اول یکی از مهمترین دلایلی باشد که خیلی ها OpenGL را  کتابخانه ای خوب (یا بهتر بگوییم آسان) توصیف میکنند. وقتی این حالت را با  DirectX مقایسه میکنیم، میبینیم که حضور تکنولوژی COM، اغلب باعث پیچیدگی  کار برنامه نویسی با آن میشود. پس شاید بتوان گفت OpenGL از این لحاظ برتری  دارد؛ زیرا بصورت یک سری فایلهای سرباره و کتابخانه ای ارائه میشود، حالتی  که برنامه نویسها سالهاست با آن آشنا هستند. 
از جمله ویژگیهای مهم OpenGL، که باعث جذب طرفداران زیادی برای آن شده  است، قابلیت اجرای آن در انواع سیستم عاملها میباشد. یعنی این کتابخانه،  برخلاف بسیاری از رقبای خودش تنها به سیستم ویندوز محدود نمیباشد و به گفته  خیلی از کاربرانش، هر جا که یک کامپیوتر وجود داشته باشد میتوان از OpenGL  هم استفاده کرد. 
درست است که OpenGL ابتدا توسط شرکت SGI ارائه شد ولی در حال حاضر  تقریبا متولی مشخصی ندارد و هر کسی میتواند یک نسخه اختصاصی از OpenGL را  نوشته و بر روی اینترنت قرار دهد تا دیگران هم از آن بهره ببرند؛ کاری که  الان شرکتهای بزرگی همچون مایکروسافت و اپل انجام داده اند و نسخه اختصاصی  از این کتابخانه را برای سیستم عاملهای خود عرضه کرده اند. در واقع OpenGL،  وصله های زیادی دارد (این وصله ها extension نامیده میشوند). الان مدتهاست  که گفته میشود قرار است نسخه OpenGL 2.0 به بازار بیاید، ولی هنوز چنین  چیزی در دنیای واقعی وجود ندارد. 
در ضمن OpenGL یک نوع ماشین حالت(state machine)  به شمار می آید. یعنی  اکثر خصوصیات و قابلیتهای آن بصورت یک تابع حالت عرضه میشوند. بدین ترتیب  که اگر مثلا خصوصیت نورپردازی آن را فعال نمایید، تا زمانی که بار دیگر این  خصوصیت را غیر فعال نکرده باشید صحنه شما تحت نورپردازی قرار میگیرد. 
اگر شما از آن دسته افرادی هستید که از اینترنت برای یافتن پاسخ  سوالهای برنامه نویسی خود استفاده میکنید، با خیال راحت به سراغ OpenGL  بروید. چون منابع زیادی در این زمینه وجود دارد و میتوانید مطمئن باشید که  هیچ یک از سوالهای شما بی پاسخ نخواهد ماند. OpenGL بر خلاف اکثر کتابخانه  های مشابه دارای مستندات کاملا استانداردی میباشد. شرکت SGI سالهاست کتابی  تحت عنوان OpenGL Red Book را عرضه کرده است که به توضیح و تشریح OpenGL  اختصاص داده شده است. همچنین کتاب OpenGL Blue Book هم بعنوان مرجع دستورات  این کتابخانه میباشد. نکته دیگر اینکه OpenGL یک کتابخانه شیء گرا نمیباشد  و همانطور که گفتیم بعنوان یک سیستم مشتری/خدمات دهنده همه امور خود را با  یک سری تابع انجام میدهد. این مسئله میتواند در مورد برنامه های بزرگ مشکل  آفرین باشد. (البته خود OpenGL بصورت مرحله ای طراحی شده است، ولی میتوان  به گونه ای برنامه را طراحی کرد که از تکنولوژی شیء گرا استفاده کند؛ هر  چند این کار خیلی راحت نمیباشد) 
از جمله امکانات خوبی که در این کتابخانه تعبیه شده است، توابع خود  فراخوان (callback) میباشد. این توابع میتوانند همانند یک متغیر بعنوان  آرگومان به یک تابع دیگر ارسال شده و در موقع مقتضی فراخوانی شوند. از این  توابع بیشتر برای اعلام خطاهای داخلی دستورات، شکستن سطوح منحنی و اعمال  مورد نیاز در حین تغییرات پنجره برنامه استفاده میشود. 
حالا اجازه دهید کمی هم راجع به معماری OpenGL بحث کنیم و ببینیم  OpenGL چطور یک صحنه را رسم میکند. در پایین ترین سطح گرافیک سه بعدی،  معمولا سه شیء اولیه نقطه، خط و چند ضلعی وجود دارند. OpenGL قادر به رسم  تک تک این اشیاء میباشد. هر چند در حوزه گرافیک کامپیوتری، عملا چیزی بنام  چندضلعی وجود ندارد و اشکالی که بیش از سه ضلع داشته باشند به مثلث تبدیل  شده و سپس رندر میگردند. (فرآیند شکستن سطوح tessellation نامیده میشود) 
OpenGL بطور پیش فرض همزمان با صادر شدن هر دستوری، عملیات مربوطه را  انجام میدهد؛ یعنی دستورات و داده ها در جایی ذخیره نمیشوند تا بعدا همگی  با هم اجرا گردند. این مسئله خود از دلائل سادگی کار با OpenGL میباشد. ولی  هنگامی که نیاز به رسم صحنه ای پیچیده داشته باشید، سرعت اجرای برنامه  خیلی اهمیت می یابد، و سادگی کار نمیتواند تنها عامل موثر باشد. در نتیجه  نیاز به بافری خواهید داشت که یک سری دستورات و داده ها را در خود ذخیره  کرده و سپس در زمان مورد نیاز همگی آنها را به یکباره اجرا کند. چنین  مکانیسمی در خیلی از کتابخانه های مشابه هم وجود دارد. مثلا در DirectX به  این مکان ذخیره گر، بافر گره یا بافر اندیس گفته میشود. در OpenGL هم مکانی  از حافظه بنام لیست نمایشی به این عمل اختصاص داده شده است. از این لیستها  میتوان برای انجام اموری مانند نمایش فونتها، بافتها، انیمیشن، ذخیره  اطلاعات گره ها و ... استفاده کرد. همچنین امکان ذخیره اکثر متغیرهای حالت  هم در این لیستها وجود دارد. از این نظر میتوان آنها را با بلاکهای حالت  (state block) در DirectX مقایسه کرد. 
OpenGL میتواند سه حالت عملیاتی داشته باشد. حالت معمولی که همان حالت  رندر نام دارد و دو حالت دیگر حالتهای انتخاب (selection) و بازخورد  (feedback) میباشند که میتوانند جهت انتخاب اشیاء در صفحه توسط کاربر (با  وسایلی مثل ماوس) و یا ارسال اطلاعات اشیاء رندر شده به جایی غیر از صفحه  (مثلا به یک فایل یا چاپگر) استفاده شوند. 
دستورات اصلی OpenGL با پیشوند gl آغاز میشوند، مثلا دستور glEnable()  مسئول فعال کردن متغیرهای حالت میباشد. glu هم پیشوندی است که قبل از نام  دستورات کتابخانه کمکی OpenGL ظاهر میشود. در OpenGL بسیاری از دستورات  دارای چندین قالب میباشند و میتوان آرگومانهای آنها را هم به شکل مقداری و  هم به شکل آرایه ای (برداری) به تابع ارسال کرد، که البته نوع آرایه ای  دستورات علی رغم پیچیده تر بودن اغلب سریعتر میباشد. برای اینکه بتوانید  اطلاعاتی هم نسبت به قابلیتهای سیستمی که برنامه روی آن اجرا میشود بدست  آورید از توابعی مثل glGetInteger، glGetFloat یا glGetBoolean استفاده  کنید. همچنین از آنجاییکه تفاوتهایی بین نسخه های مختلف OpenGL وجود دارد،  میتوانید به کمک همین توابع از قابلیتهای دقیق نسخه خود آگاه شوید. 
توابع کتابخانه کمکی هم در اصل از روی خود توابع اصلی ساخته شده اند.  تنظیم دوربین و محوطه دید، رسم اشکال سه بعدی همچون کره و استوانه، رسم  سطوح منحنی، آماده سازی تصاویر و کمک به اشکالزدایی برنامه از جمله  قابلیتهای این کتابخانه میباشند. 
یکی از مزایای OpenGL در مقایسه با رقبایش، قابلیت رندر کردن اشیاء  منحنی و سطوح درجه دو و چند جمله ای میباشد. ارزیاب (evaluator) که یک  مفهوم ریاضی میباشد در OpenGL هم جهت رندر کردن منحنی های درجه دوم بکار  میرود. همچنین در اینجا میتوانید سطوح و منحنیهای NURBS را توسط کتابخانه  کمکی رسم کنید. 
در OpenGL میتوانید دو حالت رنگی را تنظیم کنید، یکی حالت رنگی حقیقی  یا RGBA که در آن رنگها بصورت مولفه های قرمز، سبز، آبی و آلفا مشخص میشوند  و حالت اندیس رنگی که در آن کلیه رنگهای موجود درون یک پالت (جدول رنگی)  قرار میگیرند و برای استفاده از هر یک باید اندیس معادل آن رنگ را فراخوانی  کرد. این روزها استفاده از حالت پالتی کمتر رایج میباشد ولی هنوز هم جهت  حفظ سازگاری، این قابلیت در OpenGL قرار داده شده است. در واقع زمانی که  OpenGL طراحی میشد وضعیت تقریبا برعکس بود چون کارتهای گرافیکی قابلیت  نمایش تعداد کمی رنگ را داشتند، همچنین قابلیتهایی مثل dithering (مات  سازی) و halftoning (سایه سازی) که در دهه 90 برای ایجاد سایه های رنگی (و  در نتیجه افزایش تعداد رنگهای موجود) بکار گرفته میشدند در این کتابخانه  گنجانده شده اند. 
اگر بخواهیم OpenGL را از نقطه نظر جلوه های گرافیکی بررسی کنیم،  درخواهیم یافت که این کتابخانه توانسته است متناسب با زمان، اکثر قابلیتهای  پیشرفته گرافیکی را پشتیبانی کند. اعمالی همچون ترکیب رنگ (blending)، تست  و ترکیب آلفا، مه و پشته ماتریس به شکل خوبی در OpenGL پیاده سازی شده  اند. همچنین در حال حاضر سایه زنها (shader) هم در این کتابخانه قابل  استفاده میباشند و زبانهایی همچون Cg و  GLSL برای کاربرد سایه زنهای گره و  پیکسل در OpenGL عرضه شده اند تا دیگر نیازی به کدهای اسمبلی برای برنامه  نویسی ریزپردازنده های گرافیکی نباشد. یکی از اصطلاحات خاصی که بیشتر در  برنامه نویسی OpenGL رایج میباشد واژه تکه (fragment) میباشد که به گروهی  از پیکسلها اطلاق میشود. گاهی اوقات به سایه زنهای پیکسل در دنیای OpenGL،  سایه زن تکه گفته میشود. 
اموری مثل سایه زنی اشیاء (shading)، نورپردازی و بافت زنی هم با  امکانات خوبی در OpenGL پیاده سازی شده اند و در این زمینه برنامه نویس  گرافیکی مشکل زیادی را حس نمیکند. 
پیشتر گفتیم که دستوری با نام glEnable برای فعال سازی متغیرهای حالت  بکار میرود؛ جهت غیر فعال نمودن متغیرهای حالت هم میتوان از دستور  glDisable استفاده نمود. فرآیند رندر کردن هم در OpenGL خیلی پیچیده  نمیباشد. برای مثال به کد نمونه زیر توجه کنید: 



glBegin(GL_TRIANGLE); 
glNormal3f(0,1,0); 
glVertex3f(100,0,0); 
glNormal3f(0,1,0); 
glVertex3f(-100,0,0); 
glNormal3f(0,1,0); 
glVertex3f(0,0,100); 
glEnd(); 


آرگومان دستور glBegin مشخص میکند که قرار است یک مثلث رسم شود، دستور  glNormal3f هم مختصات بردار نرمال گره ای را میگیرد که مختصات آن در اولین  دستور glVertex3f بعدی خواهد آمد. بدین ترتیب یک مثلث با اضلاع 100 ساخته  میشود. در نهایت glEnd تعیین کننده پایان عملیات رندر میباشد. توجه داشته  باشید که در اینجا بلافاصله پس از صادر شدن دستور glVertex گره مورد نظر بر  روی تصویر ظاهر میشود. میتوان رنگ گره ها را هم توسط دستور glColor تعیین  کرد. 
در OpenGL همچنین امکانات خوبی برای خواندن، نوشتن، کپی و رسم مستقیم  پیکسلها وجود دارد. اصولا OpenGL کتابخانه کوچکی میباشد و تعداد دستوراتش  معمولا از 120 تجاوز نمیکند (دستوراتی که خیلی اوقات کارهای مشابه را با  دریافت آرگومانهای متفاوت انجام میدهند). 
از جمله راه های کاربرد OpenGL، استفاده از آن به موازات سایر APIها  همچون DirectInput و DirectSound میباشد زیرا این کتابخانه بطور ذاتی هیچ  نوع پشتیبانی از ادوات صوتی و ورودی ارائه نمیکند. از جمله معایب OpenGL،  عدم پشتیبانی کامل سازندگان سخت افزار میباشد. یعنی هیچ ضمانتی وجود ندارد  که یک ویژگی پیشرفته گرافیکی بر روی برنامه های OpenGL قابل پیاده سازی  باشد، اما OpenGL خود این قابلیت را دارد که کلیه اعمال سخت افزاری را توسط  CPU شبیه سازی نرم افزاری کند (البته با سرعتی پایینتر). 
یادآور میشوم که کتابخانه های OpenAL و OpenIL هم چند سالی است که به  موازات OpenGL به ترتیب برای انجام امور صوتی و ورودی برنامه ها به بازار  عرضه شده اند. 
امیدوارم شما عزیزان از این مقاله نهایت بهره را برده باشید، دنیای  گرافیک کامپیوتری، بسیار جذاب و پرهیجان میباشد، ان شاء ا... این مقاله  نقطه شروع شما برای ورود به این صنعت باشد. 

قبل از هر چيزي  براي  اينکه تکرار مکررات در تمام مثالها صورت نگيرد و  همانطور که در مقاله ي  اول نيز ذکر گرديد در برنامه نويسي  OpenGL تحت  ويندوز اولين کاري  که بايد صورت گيرد برپايي  فرمت نقطه اي  مي  باشد پس  بهتر است يک يونيت تحت همين نام ايجاد نماييم تا به دفعات از آن در سورس  هاي  ديگر نيز استفاده گردد. 
سورس کامل اين يونيت تشريفاتي  به صورت زير بوده و اين قاعده در تمام  برنامه هاي  ما تکرار و رعايت خواهد گرديد و تحت عنوان SPF به برنامه ها  الحاق مي  گردد: 



unit SPF; // setup pixel format  

interface 
uses { uses clause } 
   Windows ; 
var 
  hrc: HGLRC;  // Permanent Rendering Context 

procedure CleanUp(Handle: HDC); //Properly Kill The Window 
procedure SetDCPixelFormat(Handle: HDC;ColorBits,DepthBufferBits:integer); 

implementation 

procedure CleanUp(Handle: HDC); //Properly Kill The Window 
begin 
  if hrc<> 0 then       //Is There A Rendering Context? 
    begin 
       //Are We Able To Release Dc and Rc contexts? 
       if (not wglMakeCurrent(handle,0)) then 
         MessageBox(0,'Release of DC and RC failed.' 
                    ,' Shutdown Error',MB_OK or MB_ICONERROR); 
      //Are We Able To Delete The Rc? 
       if (not wglDeleteContext(hRc)) then 
        begin 
          MessageBox(0,'Release of Rendering Context failed.', 
                       ' Shutdown Error',MB_OK or MB_ICONERROR); 
          hRc:=0;   //Set Rc To Null 
        end; 
    end; 
end; 

procedure SetDCPixelFormat(Handle: HDC;ColorBits,DepthBufferBits:integer); 
var 
  pfd: TPixelFormatDescriptor; 
  nPixelFormat: Integer; 

begin 
  FillChar(pfd, SizeOf(pfd), 0); 

  with pfd do begin 
    nSize     := sizeof(pfd);             // Size of this structure 
    nVersion  := 1;                       // Version number 
    dwFlags   := PFD_SUPPORT_OPENGL Or PFD_DRAW_TO_WINDOW 
                 Or  PFD_TYPE_RGBA;       // Flags 
    iPixelType:= PFD_TYPE_RGBA;           // RGBA pixel values 
    cColorBits:= ColorBits;               // 24-bit color 
    cDepthBits:= DepthBufferBits;         // 32-bit depth buffer 
    iLayerType:= PFD_MAIN_PLANE;          // Layer type 
  end; 

  nPixelFormat := ChoosePixelFormat(Handle, @pfd); 
  //Did We Find A Matching Pixelformat? 
  if (nPixelFormat=0) then 
    begin 
    CleanUp(handle);                          //Reset The Display 
      MessageBox(0,'Cant''t Find A Suitable PixelFormat.' 
                      ,'Error',MB_OK or MB_ICONEXCLAMATION); 
      Halt(1); { Halt right here! } 
    end; 

  //Are We Able To Set The Pixelformat? 
  if (not SetPixelFormat(Handle, nPixelFormat, @pfd)) then 
    begin 
      CleanUp(handle);                          //Reset The Display 
      MessageBox(0,'Cant''t set PixelFormat.' 
              ,'Error',MB_OK or MB_ICONEXCLAMATION); 
      Halt(1); { Halt right here! } 
    end; 

  hrc := wglCreateContext(Handle); 
  if (hRc=0) then 
    begin 
    CleanUp(handle);                        //Reset The Display 
      MessageBox(0,'Cant''t create a GL rendering context.' 
                         ,'Error',MB_OK or MB_ICONEXCLAMATION); 
      Halt(1); { Halt right here! } 
    end; 

  //Are We Able To Activate The Rendering Context? 
  if (not wglMakeCurrent(Handle, hrc)) then 
    begin 
    CleanUp(handle);                      //Reset The Display 
    MessageBox(0,'Cant''t activate the GL rendering context.' 
                          ,'Error',MB_OK or MB_ICONEXCLAMATION); 
      Halt(1); { Halt right here! } 
    end; 

end; 

end.

با توجه به اينکه احتمالا مطالب عنوان شده در قسمت اول کمي پيچيده بودند در  طي چند مثال که به تدريج ارائه خواهد شد اين مطالب بيشتر موشکافي خواهند  گرديد. 


در اين مثال قصد داريم يک مثلث ساده را با استفاده از OpenGL ترسيم  کنيم. در اينجا با نحوه ي استفاده از توابع glViewport – glMatrixMode –  glLoadIdentity – gluPerspective- glClear -  gluLookAt – glBegin  - glEnd   بيشتر آشنا خواهيم شد.  


يک پروژه جديد در دلفي ايجاد نموده و يونيت OpenGL استاندارد دلفي و  يونيت SPF را که قبلا در طي مقاله اي راجع به آن براي پرپايي فرمت نقطه اي  صحبت گرديد را به برنامه الحاق نماييد.  
يعني: 




unit ex01;  

interface 

uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs , OpenGL, SPF; 



قاعده ي ديگري که در تمام برنامه هاي OpenGL مشترک است ايجاد يک متغير  براي دريافت HDC فرم مي باشد و پاس کردن آن به توابع موجود در يونيت SPF  براي برپايي فرمت نقطه اي با استفاده از آن. 
يعني در ادامه خواهيم داشت: 



type 
  TForm1 = class(TForm) 
    procedure FormCreate(Sender: TObject); 
  private 
    { Private declarations } 
  public 
    { Public declarations } 
  end;  

var 
  Form1: TForm1; 

implementation 

{$R *.dfm} 

var 
 f_Hdc : LongInt; 



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



procedure TForm1.FormCreate(Sender: TObject); 
begin 
  // Create a rendering context. 
  f_Hdc := GetDC(handle); 
  SetDCPixelFormat(f_Hdc,16,16); 
  InitGL; 
end; 

از برگه ي خواص رخدادهاي مربوط به فرم را انتخاب نماييد و در قسمت  OnDestory مربوط به فرم دوبار کليک کنيد تا روال رخداد آن آماده شود. از آن  براي پاکسازي برنامه استفاده خواهيم کرد (يک تعهد اخلاقي !). يعني: 



procedure TForm1.FormDestroy(Sender: TObject); 
begin 
  CleanUp(f_Hdc);// Clean up and terminate. 
end;

----------

