ورود

View Full Version : رسم سریع در Opengl



1485159
شنبه 28 فروردین 1389, 21:44 عصر
سلام
فرض کنید که من حدود 50000 نقطه(point) دارم که میخوام اونا رو رسم کنم.
در حالت عادی برنامه با کمبود سرعت مواجه میشه! هنگام استفاده از لیست های نمایشی هم بازم سرعت خیلی کم میشه!!! میخواستم بدونم که راه حل چیه؟
ممنون.

pswin.pooya
یک شنبه 29 فروردین 1389, 01:23 صبح
این ترتیب سرعت وجود داره:



VAO
VBO همراه با VIO
Display List with indexed triangles
Indexed triangled
glDraw
glBegin/glEnd



VBO از OpenGL 2 به بعد ساپورت میشه و سرعت واقعا خوبی رو ارائه میده. استفاده ازش برای مش های استاتیک و یا Hardware skinning پیشنهاد میشه
VAO از OpenGL 3.0 به بعد ارائه شده که سرعتش به خاطر نداشتن تغییر وضعیت client side از VBO بیشتره اما انعطاف فوقالعاده کمی رو داره. و درایورهای کمی ازش استفاده میکنن.
Indexed triangles: مثلث های اندیس گذاری شده بیشترین سرعت رو برای حالتی که توی هر فریم ورتکسها تغییر میکنن دارن و هنوز هم مورد استفاده زیادی دارن. توی این حالت برای رسم از glDrawElemets استفاده میشه
لیستهای نمایشی: به تاریخ ملحق شدن و مورد استفادشون رو از دست دادت
glBegin/glEnd: کندترین حالت رسم هستش که فقط برای مبتدیان پیشنهاد میشه. این نوع هم به تاریخ ملحق شده.

به طور کل VBOهای که از اندیس ها استفاده میکنن (VIO) ترجیح داده میشه که مزیتهای زیر رو دارن:


روی حافظه کارت گرافیک اطلاعات ذخیره میشه در نتیجه باس سیستم اشغال نمیشه.
با اینکه از OpenGL 2 به بعد ساپورت میشه اما تحت ویرایشهای پایین تر هم تحت الحاقی کار میکنه (یعنی ساپورت سخت افزاری بالایی داره)
تغییر وضعیتش client-side هستش پس میشه اون رو با ویرایش های مختلف GLSL به راحتی هماهنگش کرد. (قابلیت ساپورت شیدر بالایی داره)
با دو تا VBO میشه یه VIO رو به وجود آورد که سرعت رندرش به مراتب بیشتره
میشه به هر قسمتی که از اونها لازمه دسترسی داشت و برای رسم ارسالش کرد (مثلا فقط مکان ورتکسها رو ارسال کنی)

بسته به حالت های مختلف میشه راهکارهای دیگه رو هم برای افزایش سرعت به کار بردش. مثلا میشه از instancing برای مواردی که تنها موقعیت اشکال فرق میکنن استفاده کرد و یا در سیستم های ذره ای از Pont sprite ها استفاده کرد (حجم داده ارسالی رو حداقل به اندازه 1/7 کاهش میدن)

1485159
یک شنبه 29 فروردین 1389, 09:40 صبح
در مورد تابع glDrawElemets میشه توضیح بدین؟
و در مورد glDrawElemets.
ممنون.

pswin.pooya
یک شنبه 29 فروردین 1389, 10:53 صبح
فرض کن میخوام یه مثلث بکشم.

اول یه آرایه برای ورتکس ها و رنگ اونها میسازم:


float v[] ={-1,-1,0, 1,0,0,
1,-1,0, 0,1,0,
0,1,0, 0,0,1}

سه float اول برای مکان و سه تای دیگه برای رنگ هستن. این آرایه شامل اطلاعات شکل هندسی من هستش.

حالا باید یه آرایه برای اندیس ها بسازم که مثلث ها رو مشخص کنم:


unsigned i[]={0,1,2};

این آرایه به حاوی اندیس هایی هستش که به آرایه اول اشاره میکنن. به عنوان مثال اینجا میگه برای رسم مثلث اول اندیس شماره 0 و بعد 1 و بعد از اون 2 رو بردار.

بعد از اینکه آرایه ها آماده شد باید وضعیت های client رو روشن کنم تا OpenGL بتونه تشخیص بده که قراره چی رسم بشه. اینجا من فقط می خوام از مکان و رنگ استفاده کنم:


glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

حالا باید به OpenGL بگم که هر کدوم از اطلاعات کجای آرایه و به چه شکلی قرار داره:


glVertexPointer(3, GL_FLOAT, sizeof(float) * 6, v);
glColorPointer(3, GL_FLOAT, sizeof(float) * 6, (v + sizeof(float) * 3));

پارامتر اول تعداد کامپوننت ها رو مشخص میکنه: اینجا هم رنگ و هم مکان از سه کامپوننت تشکیل شدن.
پارامتر دوم نوع کامپوننت ها رو مشخص میکنه: اینجا نوع هر دوشون float هستش
پارامتر سوم stride یا فاصله اطلاعات هر ورتکس با ورتکس دیگه رو توی آرایه مشخص میکنه که از اونجا که هر ورتکس 6 تا کامپوننت float داره پس فاصله اونها میشه sizeof(float) * 6
پارامتر چهارم: مکان اطلاعات رو مشخص میکنه: مثلا برای مکان v هستش و برای رنگ v + 12 هستش (چون 3 تا float از اول آرایه فاصله داره). توی اینجور موارد ساختن یه struct میتونه مطمئن تر باشه.

حالا باید اطلاعات رو برای رسم ارسال کنیم:

glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, i);
پارامتر اول نوع رسم رو مشخص میکنه.
پارامتر دوم تعداد اندیس ها
پارامتر سوم نوع اندیس ها (از لحاظ ذخیره سازی توی حافظه)
پارامتر چهارم اشاره گر آرایه اندیس ها رو می گیره.

هر سه تا اندیس باعث رسم یک مثلث میشه.

و در پایان باید وضعیتها رو غیر فعال کنیم:

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

1485159
یک شنبه 29 فروردین 1389, 21:04 عصر
من کد زیر رو قرار میدم ولی کار نمیکنه!

int DrawGLScene(GLvoid)
{
float v[] ={ 0, 0, 0 , 1,0,0,
10,10, 0 , 0,1,0,
10, 0, 0 , 0,0,1};
unsigned i[]={0,1,2};

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();

// glTranslatef(mouse_x, mouse_y, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(float) * 6, v);
glColorPointer(3, GL_FLOAT, sizeof(float) * 6, (v + sizeof(float) * 3));
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, i);

glPopMatrix();
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
return true; // Everything went OK
}
مشکل از چیه؟
ممنون.

1485159
یک شنبه 29 فروردین 1389, 21:28 عصر
البته در حالت 2 بعدی!

pswin.pooya
یک شنبه 29 فروردین 1389, 22:08 عصر
دو تا مشکل ممکنه وجود داشته باشه:

1. پارامتر آخر اشاره گرها درست نباشن. من معمولا struct استفاده میکنم و مکان اون رو میدم

2. مختصاتی رو که دادی اشتباه باشه. فکر کنم اینجا استفاده از 10 برای رسم بزرگ باشه. و همینطور مختصات مثلث ناجور هستش. بهتره اول این مختصات رو با glBegin تست کنی.

1485159
یک شنبه 29 فروردین 1389, 22:22 عصر
1. پارامتر آخر اشاره گرها درست نباشن. من معمولا struct استفاده میکنم و مکان اون رو میدم
نگرفتم! میشه یه مینه کد بزارید؟

2. مختصاتی رو که دادی اشتباه باشه. فکر کنم اینجا استفاده از 10 برای رسم بزرگ باشه. و همینطور مختصات مثلث ناجور هستش. بهتره اول این مختصات رو با glBegin تست کنی.
نه برادر! سیستم مختصات رو به پیکسل تنظیم کردم! درسته!
=======================================
=======================================
فکر کنم اگه بگم میخوام چیکار کنم بهتر بتونید راهنمایی کنید:
من میخوام از یک فایل یه تعداد مختصات(پیکسل) و رنگ اون ها رو بگیرم و رسم کنم!
ممنون.

pswin.pooya
یک شنبه 29 فروردین 1389, 23:42 عصر
مشکل از همون glColorPointer بودش:



#include <GL/glut.h>

#pragma comment(lib,"opengl32.lib")

void draw()
{
glClear (GL_COLOR_BUFFER_BIT);

float v[]= { -1,-1,0, 1,0,0,
1,-1,0, 0,1,0,
0,1,0, 0,0,1};
unsigned int i[] = {0,1,2};

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

glVertexPointer(3,GL_FLOAT,sizeof(float) * 6,v);
glColorPointer(3,GL_FLOAT,sizeof(float) * 6,v + 3);

glDrawElements(GL_TRIANGLES,3,GL_UNSIGNED_INT,i);

glutSwapBuffers();
}

void init()
{
glClearColor(1,1,1,1);
}

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

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(400, 400);
glutCreateWindow("Test glDraw");
init();
glutDisplayFunc(draw);
glutIdleFunc(draw);
glutMainLoop();
return 0;
}

1485159
یک شنبه 29 فروردین 1389, 23:59 عصر
ممنون درست شد.
اگه بخوام از رنگ alpha هم استفاده کنم چیکار کنم؟
در مورد :

فکر کنم اگه بگم میخوام چیکار کنم بهتر بتونید راهنمایی کنید:
من میخوام از یک فایل یه تعداد مختصات(پیکسل) و رنگ اون ها رو بگیرم و رسم کنم!
ممنون.
هم میشه راهنمایی کنید؟
ممنون.

pswin.pooya
دوشنبه 30 فروردین 1389, 00:40 صبح
در مورد دستورهای glColorPointer و glVertexPointer یه سرچ بزن و مطالعه کن.

برای فایل هم اگر از فایل مدل استفاده میکنی مثل 3ds بهتر هست که کتاب focus on 3d models رو مطالعه کنی.

1485159
دوشنبه 30 فروردین 1389, 00:44 صبح
برای فایل هم اگر از فایل مدل استفاده میکنی مثل 3ds بهتر هست که کتاب focus on 3d models رو مطالعه کنی.
نه یه فایل مندر آوردی که خودم تولید کردم!

1485159
چهارشنبه 12 خرداد 1389, 21:58 عصر
گفتید که مثلث های اندیس گذاری شده برای زمانی خوبه که ورتکس ها تغییر میکنن؟ اگه نکنن چی؟ منظورم اینه که مثلا اطلاعات رو توی ورتکس ها ذخیره کنیم و بعد هنگام رسم مختصات رو تغییر بدیم(glTranslate) و اشکال جابجا بشن؟
--------
اگه ورتکس ها زیاد نباشن از چه روشی استفاده کنم؟

pswin.pooya
چهارشنبه 12 خرداد 1389, 22:15 عصر
نه اشتباه گرفتی. برای زمانی که ورتکسها تغیرر میکنن استفاده از glDraw موثرتر از بافرها هستش. مگر اینکه بافرها رو روی حافظه مپ کنی. اگر ورتکسها تغییر نکنن. استفاده از VBO بهرتین گزینه (به همراه IBO یا همون اندیسها هستش.).

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

1485159
چهارشنبه 12 خرداد 1389, 22:25 عصر
نه اشتباه گرفتی. برای زمانی که ورتکسها تغیرر میکنن استفاده از glDraw موثرتر از بافرها هستش.
آخه قراره که فقط مختصات رسم تغییر کنه نه ورتکس ها! مثلا یه بار اطلاعات رو توی آرایه ذخیره میکنم و بعد با تغییر دادن مختصات(به وسیله glTranslate) جابجا میشن.

مگر اینکه بافرها رو روی حافظه مپ کنی
کجا ذخیره کنم؟

استفاده از VBO بهرتین گزینه (به همراه IBO یا همون اندیسها هستش.).
آخه میخوام تو همه ی کارت های گرافیک کار کنه.
---
منظور از glDraw همون glbegin و glend هست؟

pswin.pooya
چهارشنبه 12 خرداد 1389, 22:57 عصر
منظور از glDraw همون glbegin و glend هست؟

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

برای مثلث ها( وبقیه اشکال):
http://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml

برای مثلث هایی که از اندیس استفاده میکنن:
http://www.opengl.org/sdk/docs/man/xhtml/glDrawElements.xml


فصل 10 (اگر اشتباه نکنم) کتاب begining opengl game programming در این مورد توضیح کامل داده.

1485159
چهارشنبه 12 خرداد 1389, 23:04 عصر
نه. این دستورها برای رسم آرایه ای از ورتکسها به کار میرن

برای مثلث ها( وبقیه اشکال):
http://www.opengl.org/sdk/docs/man/x...DrawArrays.xml (http://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml)

برای مثلث هایی که از اندیس استفاده میکنن:
http://www.opengl.org/sdk/docs/man/x...awElements.xml (http://www.opengl.org/sdk/docs/man/xhtml/glDrawElements.xml)
همون توضیحاتی که صفحه قبل دادیده دیگه؟(مثلث های اندیس گذاری شده؟)

sajjadgameactor
پنج شنبه 13 خرداد 1389, 14:30 عصر
میشه یک کتاب که برای opengl که خوب توضیح داده باشه و از جدیدترین فناوری هاش استفاده کرده باشه معرفی کنید
(اگه لینک دانلودش بگذارید دیگه شرمنده میکنید:لبخند:)
ببخشید ربط چندانی به موضوع نداره ولی چون کمتر از 20 تا پست دارم نمیتونم پیغام خصوصی بدم

pswin.pooya
یک شنبه 16 خرداد 1389, 17:40 عصر
میشه یک کتاب که برای opengl که خوب توضیح داده باشه و از جدیدترین فناوری هاش استفاده کرده باشه معرفی کنید
(اگه لینک دانلودش بگذارید دیگه شرمنده میکنید:لبخند:)
ببخشید ربط چندانی به موضوع نداره ولی چون کمتر از 20 تا پست دارم نمیتونم پیغام خصوصی بدم

opengl.persiangig.com