الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

Display Lists في opengl .. .

مغلق
بدأه Abdullah.Alshammeri في 20 فبراير 2006 · 3 رد · 1,964 مشاهدة · في OpenGL
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم :

Display Lists

هذا الوضوع مهم للغاية .

وأيضا ممتع .. وسهل .. ومفيد .. وو وو >>> يمدح مواضيعه .

الفائدة الاساسية من Display Lists هي تسريع التطبيق .

فمثلا لنفرض أنك تريد انشاء خمس وستين مكعب .. ( صناديق ) ,, لتضعها في لعبتك .

الحل البديهي هو .. شبيه بالتالي :

FOR(I=0;I<=65; I++)
{
glTranslatef(1,1,0);
CUBE(2);
}

طبعا تضعها في Loop حتى ترسم وتبقى محدثة ,

لكن هذه ليست الطريقة السليمة .. فأثناء الLoop الجهاز يعاني الامرين من كثرة المضلعات التي تنشئها داخل Loop .. ولو كانت قليلة .. فما بالك بعدد ضخم من المكعبات .

قالوا الحل :

نرسم مكعب واحد خارج ال loop ثم نجعلها كقائمة واحدة .. ثم نستدعي هذه القائمة .. بعدد المرات التي نريد . ,,

طبعا هذه الطريقة تتضح فائدتها ,, عندما نرسم مضلعات كبيرة وكثيرة .. وتحتوي على اوامر ترهق المعالج .. مثل الدوال المثلثية .

الكتاب الاحمر .. ضرب مثال جدا واضح .. راجعه .

باختصار : ال Display List . . . هدفها عمل أشياء كثيرة خارج ال loop .. ثم اثناء ال Loop يكون كل شيء قد تم تجهيزه .

والجميل فيها انك تستطيع عمل اكثر من قائمة ( list ) .. ثم كل قائمة لها رقم محدد ..

وبالتالي تنادي هذه القائمة من خلال رقمها ..

واذا أردت مسح هذه القائمة تستطيع ذلك . . .

الامر جدا مفيد .

طيب .. خلونا نتناقش في مثال .. صغير .

اولا وضعت ثلاث دوال رئيسية .

الاولى اسمها

MakeList

وتصنع القوائم التي نريد .

الثانية اسمها :

Init

وسنضع فيها اعدادات opengl .. من اضاءة .. وغيرها .

الثالثة اسمها :

render

والتي سنرسم فيها :

void MakeList()
{

   
/*1*/	glNewList( 1, GL_COMPILE);

/*2*/	glutSolidTeapot(1);

/*3*/	glEndList();

}

في السطر الاول : اعلنا عن بدء قائمة جديدة ..

البارمتر الاول رقم القائمة ..

اذا اردت لاحقا استدعائها فستستدعيها من خلال هذا الرقم .

البارمتر الثاني : يأخذ اما :

GL_COMPILE_AND_EXECUTE

او

GL_COMPILE

بصراحة ما ادري وش الفرق .. اذا أحد يعرف يقول .

في السطر الثاني ترسم او تنفذ الاشكال التي تريد .

في الساطر الثالث .. تنهي الList

void Init()
{
   glClearColor(0.0, 0.0, 0.0, 0.0);  
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_LIGHTING);
     glEnable(GL_LIGHT0);
/*1*/	MakeList();
}

ثم ننتقل الى دالة اعداد opengl والتي تنفذ مرة واحدة .. ونستدعي دالة MakeList التي عملناها قبل قليل ..

    
void render(void) 
{
  loop++; 

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  
/*1*/	for(i=-4;i<=4;i+=2)
/*2*/	{
/*3*/	for(j=-4;j<=4;j+=4)
/*4*/	{
/*5*/	glPushMatrix();

/*6*/	glTranslatef(j,i,-20);
/*7*/	glRotatef(loop,0,1,0);

/*8*/	glCallList(1); 

/*9*/	glPopMatrix(); 
/*10*/	}

/*11*/	}
  glutSwapBuffers();

}

هنا التطبيق العملي ..

سوينا حلقة تكرارية لرسم عدد كبير من المجسمات ,, واستفدنا من display list .. التي تسرع لنا العملية .

لاحظ في السطر الثامن طريقة استدعاء القائمة ..

قمنا باستدعاء القائمة رقم وحد التي انشأناها قبل قليل .

لكن لا تفرح كثيرا بسهولة ذلك الكود فهو ليس الطريقة المثالية المستخدمة .

المفترض أن نطلب من opengl ان تحجز عدد القوائم المطلوبة .. وبالتالي هي تخبرنا

بالقائمة الفارغة .. ونحن نستنتج ما يليها :

هكذا :

int DS =0;
DS=glGenLists(3);

طلبنا من opengl حجز ثلاث ليستات .. ( قوائم) .. opengl ستعيد رقم قائمة فارغة ..

نحن نستنتج الباقي .

  glNewList(DS,GL_COMPILE);
.
.
.
glEndList();

  glNewList(DS+1,GL_COMPILE);
.
.
.
glEndList();

  glNewList(DS+2,GL_COMPILE);
.
.
.
glEndList();

ثم نمسح القوائم عند انتهاء التطبيق ..

لاحظ

/*1*/	int first=0;
/*2*/	int second=0;
/*3*/	first = glGenLists(12);
/*4*/	second = glGenLists(1);
/*5*/	printf("one  %d   two  %d  ",(int)first,(int)second);

في السطر الثالث حجزنا 12 قائمة جديدة .

ستكون قيمة المتغير first هي 1 .

اما المتغير second فهي 13 .. لاننا حجزنا قبله 12 قائمة .

أتمنى تكون الفكرة وصلت .

مثال :

	GLuint first=0;
  first = glGenLists(12);


	glNewList(first,GL_COMPILE);
  drawCube();
	glEndList();

	glNewList(first+1,GL_COMPILE);
  drawCy();
	glEndList();

	glNewList(first+2,GL_COMPILE);
  drawSphere();
	glEndList();

	.
	.
	.
	.
	glCallList(first+1);

ثم اذا انتهيت من التطبيق تمسح القوائم من الذاكرة .

glDeleteLists(first,12);

تطلب بارمترين :

الاول : رقم اول قائمة عملتها .. وهي هنا first .

الثاني : رقم اخر قائمة عملتها ( القوائم التي حجزت ) .. وهي هنا 12

والقوائم التي بين 1 و 12 ستمسح ايضا .

وهذه بعض الملاحظات :

1- تستطيع بناء قائمة داخل قائمة ( قوائم متداخلة ) ,,

مثال :

glNewList(1,GL_COMPILE)
Cube(3);
glEndList()
glNewList(2,GL_COMPILE)
glCallList(1);
glEndList();

ولكن لا تحاول ان تكثر من هذه الطريقة لان هناك حدود لك .. : ) ,, ابحث في هذا الرابط للمزيد .

3- يوجد بعض الاوامر التي لا يصلح وضعها داخل glNewList ..

راجعها في المراجع ..

4- من أهم تطبيقات DL تصيير النصوص . . . (Text Render)

تدريب :P

قم بعمل مثال يرسم الكثير من المضلعات ..

مرة باستخدام list

ومرة بدون استخدام list ..

وقم بحساب FPS .. لكل منهما ..,,, ولاحظ الفرق .

======

المرفق .. glut ..

بصراحة كنت أتمنى تغيير المثال .. الى مكعبات بدلا من teapot .. حتى تقل عدد المضلعات .. لكن تكاسلت !!

display_lists.zip

تم تعديل هذه المشاركة بواسطة الشمري في 20 فبراير 2006 في 23:16

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#2

السلام عليكم

درس طيب أخى الشمرى. و لكن أحب التعقيب على نقطة معينه. فكرة الـDisplay List تتمثل فى الأتى:

أى شئ يظهر على الشاشة صوتا كان أم نصا أم صورة أم صوت وصورة يجب أن ينتقل أولا إلى الذاكرة, و بعدما ينتقل إلى الذاكرة يتم عرضه على الشاشة و هذا هو سر أنك تسمع البعض يقول لك(الذاكرة التى فى جهازك ضعيفة :) يجب عليك كى ترى تلك اللعبة الحديثة أو الفيلم الديجتال أن تشترى Ram لجهازك أقوى و أفضل).حسنا, و لكن السؤال ما الذى تفعله الـDisplay List؟ فرضا أنك تريد رسم مكعب, فعند عمل الأسلوب Loop كما ذكرت فإن ما سيحدث هو بطء فى عملية الرسم . أما فى حالة الـDisplay List فأنت تقوم بنقل المكعب إلى الذاكرة مرة واحدة و بدلا من أن يتم رسم المكعب من أمر الرسم إلى الذاكرة.(يتم الرسم من الذاكرة إلى الذاكرة) أعتقد أن المسألة باتت واضحة. هذا بالفعل سيضر كثيرا بالذاكرة و لكن لا يتم إنكار إنه سيكون إتمام عملية الرسم بسرعة كبيرة جدا. فهى عملية نسخ من ذاكرة إلى ذاكرة أخرى. فهى تغنيك عن تكرار الأمر و البدء فى معالجة المعادلة الواحدة أكثر من مرة. و لكن؟ هل مستعد لإرهاق ذاكرتك من أجل رؤية سريعة للرسوم. الأمر متروك لك :rolleyes: .

و السلام ختام

عندما أعلن حبى لشىء فى البرمجة فذلك معناه أنه أفضل بالنسبة لى من حيث المميزات و الامكانات

OpenGL-3-revolution.jpg

#3

اعتقد اني سأستخدمها فقط في تصيير النصوص .,,,

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#4

السلام عليكم

بمعنى أصح حتى يفهم بقية الأعضاء بشكل أفضل. فرضا لو أنك تريد رسم ستين مكعب, و كل مكعب مثلا يحتاج إلى دقيقة كى يتم رسمه, فإن القت المطلوب هو 60 دقيقة للرندر. أما مع إستخدام الـDisplay List فسيتم عمل رندر مرة واحدة للمكعب . أما الـ59 مكعب الباقيين فسيتم رسمهم إعتمادا على البيانات التى سبق أن تم تسجيها فى الذاكرة, و حينها لن تتكلف من الوقت سوى وقت إنتقال البيانات من مكان إلى مكان آخر فى الذاكرة . و على إفتراض أن وقت إنتقال بيانات المكعب الواحد يساوى خمس ثوان فستكون النتيجة هى 59 × 5= 295 ثانية + دقيقة واحدة(وقت عمل رندر للمكعب الأول)= 355 ثانية بدلا من 60 دقيقة. أليس الأمر يستحق؟ :rolleyes:

والسلام ختام

عندما أعلن حبى لشىء فى البرمجة فذلك معناه أنه أفضل بالنسبة لى من حيث المميزات و الامكانات

OpenGL-3-revolution.jpg

هذا الموضوع مغلق.

مواضيع مشابهة