OpenGL - тормоза
От: gunf  
Дата: 21.06.04 07:52
Оценка:
Здравствуйте.

Делаю 3D viewer на OpenGL и при наличии файла более 1.5 Мб (около 100 000 точек — рисую просто линии) — тормоза + 98% проца.
Что можно сделать?
Re: OpenGL - тормоза
От: hemmul США  
Дата: 21.06.04 07:57
Оценка:
Здравствуйте, gunf, Вы писали:

G>Здравствуйте.


G>Делаю 3D viewer на OpenGL и при наличии файла более 1.5 Мб (около 100 000 точек — рисую просто линии) — тормоза + 98% проца.

G>Что можно сделать?
первое что приходит в голову — оптимизировать
рассакжи поподробнее как ты сейчас всё рисуешь...

vox clamantis in deserto
Re[2]: OpenGL - тормоза
От: gunf  
Дата: 21.06.04 08:16
Оценка:
Рисую так:
Пишу ну C++ Builder 5.
Сделал (делаю) компоненту на основе TCustomPanel — с OpenGL.
Вот кусок кода (2 функции) — где я рисую на панели:
//---------------------------------------------------------------------------
void __fastcall TMyPanel::PanelIdle(TObject*, bool& done)
{
    done = false;
    Paint();
}
//---------------------------------------------------------------------------
void __fastcall TMyPanel::Paint(void)
{
  //TCustomPanel::Paint();
  if (FOnPaint)
     {
      HPALETTE OldPalette=NULL;

      if (Palette)
         {
          OldPalette=SelectPalette(DisplayDeviceContext,Palette,FALSE);
          if (RealizePalette(DisplayDeviceContext)==GDI_ERROR)
             {
              ShowMessage("RealizePalette:"+IntToStr(GetLastError()));
              return;
             }
        }

      if (wglMakeCurrent(DisplayDeviceContext,GLRenderingContext)==false)
         {
          ShowMessage("wglMakeCurrent:" + IntToStr(GetLastError()));
          return;
         }

      FOnPaint(this);

      if ((FSwapBuffers==Auto) && (DoubleBuffer))
            ::SwapBuffers(DisplayDeviceContext);

      if (OldPalette)
             wglMakeCurrent(NULL, NULL) ;
    }
 return;
}
//---------------------------------------------------------------------------

Функция PanelIdle — вызывается когда Application->OnIdle — простой. Делаю это для того, чтобы, например, при OnMouseWellDown (Up) — увеличивать масштаб и ets ...

В самой проге — использую компонент и гружу файл (текстовый с координатами~ 100 000 координат)
в событии OnPanelPaint вызываю glCallList в котором уже сформирована матрица с точками. Т.е.:
//---------------------------------------------------------------------------
void __fastcall TMain::PanelPaint(TObject *Sender)
{
        Panel->Clear();
        glCallList(List_Name);//ListName - список изображения
}
//---------------------------------------------------------------------------

А сам список формирую так:
        List_Name = glGenLists(1);
        glNewList(List_Name,GL_COMPILE);
        Panel->SetPenColor(clRed);//Цвет пена
        Panel->SetScreenColor(clWhite);//цвет фона
        Panel->Mesh(Mesh);//финкция отрисовки сети см. ниже
    glEndList();

//---------------------------------------------------------------------------
 void __fastcall TMyPanel::Mesh    (SURF matr)
{
     for (int i = 0; i<int(matr.size()); i++)
        {
         for (int j = 1; j<int(matr[i].size()); j++)
          {
         glBegin(GL_LINES);
         glVertex3d(matr[i][j-1].x,matr[i][j-1].y,matr[i][j-1].z);
         glVertex3d(matr[i][j].x,matr[i][j].y,matr[i][j].z);
         glEnd();
          }
        }
}
//---------------------------------------------------------------------------



Вот в принципе и все.
Но 99 % проца — не есть весело
Re[3]: OpenGL - тормоза
От: andy_k  
Дата: 21.06.04 09:53
Оценка:
Здравствуйте, gunf, Вы писали:

.....

а что за видюха ?
ты точно дисплейный лист только один раз строишь при загрузке файла ?
и зачем wglMakeCurrent каждый раз вызывать ? у тебя несколько тредов чтоли ?
Re[4]: OpenGL - тормоза
От: gunf  
Дата: 21.06.04 10:03
Оценка:
Здравствуйте, andy_k, Вы писали:

_>а что за видюха ?

_>ты точно дисплейный лист только один раз строишь при загрузке файла ?
_>и зачем wglMakeCurrent каждый раз вызывать ? у тебя несколько тредов чтоли ?


Видяха
NVIADIA GeForse 3 Ti 500
точно один раз.
wglMakeCurrent — вызываю тока один раз:
void __fastcall TMyPanel::Paint(void)
{
  //TCustomPanel::Paint();
  if (FOnPaint)
     {
      HPALETTE OldPalette=NULL;

      if (Palette)
         {
          OldPalette=SelectPalette(DisplayDeviceContext,Palette,FALSE);
          if (RealizePalette(DisplayDeviceContext)==GDI_ERROR)
             {
              ShowMessage("RealizePalette:"+IntToStr(GetLastError()));
              return;
             }
        }

      if (wglMakeCurrent(DisplayDeviceContext,GLRenderingContext)==false)
         {
          ShowMessage("wglMakeCurrent:" + IntToStr(GetLastError()));
          return;
         }

      FOnPaint(this);

      if ((FSwapBuffers==Auto) && (DoubleBuffer))
            ::SwapBuffers(DisplayDeviceContext);

      if (OldPalette)
             wglMakeCurrent(NULL, NULL) ;
    }
 return;
Re[3]: OpenGL - тормоза
От: hemmul США  
Дата: 21.06.04 13:22
Оценка: 1 (1)
Здравствуйте, gunf, Вы писали:

оптимизировать имхо нужно здесь:

G>в событии OnPanelPaint вызываю glCallList в котором уже сформирована матрица с точками. Т.е.:

G>
G>//---------------------------------------------------------------------------
G>void __fastcall TMain::PanelPaint(TObject *Sender)
G>{
G>        Panel->Clear();
G>        glCallList(List_Name);//ListName - список изображения
G>}
G>//---------------------------------------------------------------------------
G>


так как это функция мсполняется каждый кадр.
1. что делает Panel->Clear()?
2. точек действительно очень много. их все рисовать хоть glCallLists() хоть Vertex Array-ами — всё равно много. а выводить нужно все точки? может некая часть выходит из области видимости? тогда нужно копать в сторону усечений...

vox clamantis in deserto
Re[3]: OpenGL - тормоза
От: rikkitikkitavi Россия  
Дата: 22.06.04 07:23
Оценка:
Здравствуйте, gunf, Вы писали:

G>//---------------------------------------------------------------------------

G> void __fastcall TMyPanel::Mesh (SURF matr)
G>{
G> for (int i = 0; i<int(matr.size()); i++)
G> {
G> for (int j = 1; j<int(matr[i].size()); j++)
G> {
G> glBegin(GL_LINES);
G> glVertex3d(matr[i][j-1].x,matr[i][j-1].y,matr[i][j-1].z);
G> glVertex3d(matr[i][j].x,matr[i][j].y,matr[i][j].z);
G> glEnd();
G> }
G> }
G>}
G>//---------------------------------------------------------------------------

1. я бы сделал так
void __fastcall TMyPanel::Mesh (SURF matr)
{
glBegin(GL_LINES);
for (int i = 0; i<int(matr.size()); i++)
{
for (int j = 1; j<int(matr[i].size()); j++)
{
glVertex3d(matr[i][j-1].x,matr[i][j-1].y,matr[i][j-1].z);
glVertex3d(matr[i][j].x,matr[i][j].y,matr[i][j].z);
}
}
glEnd();
}

2. уточни — тормоза в коде по части OpenGL или в коде считывания данных из файла (почему бы не бинарник при такий объемах?) и их преобразования?
Re[4]: OpenGL - тормоза
От: gunf  
Дата: 22.06.04 07:26
Оценка:
Здравствуйте, rikkitikkitavi, Вы писали:


R>2. уточни — тормоза в коде по части OpenGL или в коде считывания данных из файла (почему бы не бинарник при такий объемах?) и их преобразования?


тормоза в коде по части OpenGL . Жрет 99% проца
При отрисовке маленьих обьектов все ок.
Re[4]: OpenGL - тормоза
От: gunf  
Дата: 22.06.04 07:28
Оценка:
ЗЫ
А файл текстовый — потому, что это экспорт из Autocad. )так быстрее (
Re[5]: OpenGL - тормоза
От: rikkitikkitavi Россия  
Дата: 22.06.04 08:36
Оценка:
Здравствуйте, gunf, Вы писали:

G>тормоза в коде по части OpenGL . Жрет 99% проца

G>При отрисовке маленьих обьектов все ок.

тогда такая еще мысль — уверен, что выбранный тобой DC использует аппаратную реализацию OpenGL (т.е. ускорение видеокарточкой)?
Re[3]: OpenGL - тормоза
От: rikkitikkitavi Россия  
Дата: 22.06.04 09:16
Оценка:
Здравствуйте, gunf, Вы писали

GРисую так
GПишу ну C++ Builder 5.
GСделал (делаю) компоненту на основе TCustomPanel — с OpenGL.
GВот кусок кода (2 функции) — где я рисую на панели
G[code]
G---------------------------------------------------------------------------
Gvoid __fastcall TMyPanelPanelIdle(TObject, bool& done)
G{
G done = false;
G Paint();
G}
G---------------------------------------------------------------------------
Gvoid __fastcall TMyPanelPaint(void)
G{
G TCustomPanelPaint();
G if (FOnPaint)
G {
G HPALETTE OldPalette=NULL;

G if (Palette)
G {
G OldPalette=SelectPalette(DisplayDeviceContext,Palette,FALSE);
G if (RealizePalette(DisplayDeviceContext)==GDI_ERROR)
G {
G ShowMessage(RealizePalette+IntToStr(GetLastError()));
G return;
G }
G }

G if (wglMakeCurrent(DisplayDeviceContext,GLRenderingContext)==false)
G {
G ShowMessage(wglMakeCurrent + IntToStr(GetLastError()));
G return;
G }

G FOnPaint(this);

G if ((FSwapBuffers==Auto) && (DoubleBuffer))
G SwapBuffers(DisplayDeviceContext);

G if (OldPalette)
G wglMakeCurrent(NULL, NULL) ;
G }
G return;
G}
G---------------------------------------------------------------------------
G[code]
GФункция PanelIdle — вызывается когда Application-OnIdle — простой. Делаю это для того, чтобы, например, при OnMouseWellDown (Up) — увеличивать масштаб и ets ...

1. я правильно понял, что на каждое событие OnIdle ты отрисовываешь свою графику xz имхо, такое никак не рулит


G void __fastcall TMyPanelMesh (SURF matr)
G{
G for (int i = 0; iint(matr.size()); i++)
G {
G for (int j = 1; jint(matr[i].size()); j++)
G {
G glBegin(GL_LINES);
G glVertex3d(matr[i][j-1].x,matr[i][j-1].y,matr[i][j-1].z);
G glVertex3d(matr[i][j].x,matr[i][j].y,matr[i][j].z);
G glEnd();
G }
G }
G}
G[code]

2. а что это за структура такая SURF случаем обращение по индексам (matr[i][j-1]) — это не через свойства (с каким-нибудь кодом проверки индексов или еще чего)

З.Ы.
думаю — надо точно локализовать медленное место и оптимизировать его по максимуму
удачи
Re[4]: OpenGL - тормоза
От: gunf  
Дата: 22.06.04 09:26
Оценка:
Здравствуйте, rikkitikkitavi, Вы писали:

R>1. я правильно понял, что на каждое событие OnIdle ты отрисовываешь свою графику xz имхо, такое никак не рулит


А почему ты считаешь что такое не канает?



R>2. а что это за структура такая SURF случаем обращение по индексам (matr[i][j-1]) — это не через свойства (с каким-нибудь кодом проверки индексов или еще чего)


matrp[][] — это ветор примерно выглядит так:
class POINT3D
{
private:
   double getxyz(int i);
   void   setxyz(int i,double v);
protected:

public:
double x,y,z;
   POINT3D():x(0),y(0),z(0){};
   __property double xyz[int] = { read = getxyz , write = setxyz };
};
typedef std ::vector<POINT3D,std::allocator<POINT3D> >LINE;
typedef std ::vector<LINE,std::allocator<LINE> >SURF;

Вот SURF и есть matr %)

R>удачи



БОЛЬШОЕ СПС %)
Re[5]: OpenGL - тормоза
От: rikkitikkitavi Россия  
Дата: 22.06.04 09:48
Оценка:
Здравствуйте, gunf, Вы писали:


R>>1. я правильно понял, что на каждое событие OnIdle ты отрисовываешь свою графику xz имхо, такое никак не рулит

G>А почему ты считаешь что такое не канает?

1.потому что слишком часто вызывается. вспомни конвеер обработки сообщений
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_idle_loop_processing.asp


G>matrp[][] — это ветор примерно выглядит так:

G>
G>class POINT3D
G>{
G>private:
G>   double getxyz(int i);
G>   void   setxyz(int i,double v);
G>protected:

G>public:
G>double x,y,z;
G>   POINT3D():x(0),y(0),z(0){};
G>   __property double xyz[int] = { read = getxyz , write = setxyz };
G>};
G>typedef std ::vector<POINT3D,std::allocator<POINT3D> >LINE;
G>typedef std ::vector<LINE,std::allocator<LINE> >SURF;
G>

G>Вот SURF и есть matr %)

2. нуу, я так и думал
попробуй что-нибудь типа

int nLines = 100;
int nPoints = 100;
double* matr = new double[nLines][nPoints];
...
for (int i=0; i<nLines; i++)
    delete[] matr[i];
delete[] matr;


это должно значительно ускорить (т.к. прямое обращение к памяти)
написал на вскидку — на счет компилируемости не уверен, да и с уничтожением надо разобраться
Re[3]: OpenGL - тормоза
От: rikkitikkitavi Россия  
Дата: 22.06.04 09:53
Оценка:
да, вот еще что забыл — есть у меня компонент типа твоей панели, я ей пользовался, работает без проблем,,
если не хочешь изобретать велосипед, давай мыло — скину (откуда скачал не помню)
Re[6]: OpenGL - тормоза
От: gunf  
Дата: 22.06.04 10:22
Оценка:
Здравствуйте, rikkitikkitavi, Вы писали:

G>>А почему ты считаешь что такое не канает?


R>1.потому что слишком часто вызывается. вспомни конвеер обработки сообщений


Я пробовал без Idle — все равно 99 % проца.
Жду компоненту — могет там как-то подругому сделано?

С уважением, GunF
Re[4]: OpenGL - тормоза
От: gunf  
Дата: 22.06.04 10:22
Оценка:
Здравствуйте, rikkitikkitavi, Вы писали:

G>>А почему ты считаешь что такое не канает?


R>1.потому что слишком часто вызывается. вспомни конвеер обработки сообщений


Я пробовал без Idle — все равно 99 % проца.
Жду компоненту — могет там как-то подругому сделано?

С уважением, GunF
Re[5]: OpenGL - тормоза
От: RikkiTikkiTavi Россия  
Дата: 22.06.04 10:54
Оценка:
Здравствуйте, gunf, Вы писали:

G>Я пробовал без Idle — все равно 99 % проца.

G>Жду компоненту — могет там как-то подругому сделано?

на сколько я понял — тормозит при генерации display list, а не при отрисовке (это разные вещи)
Re[6]: OpenGL - тормоза
От: hemmul США  
Дата: 22.06.04 12:59
Оценка:
Здравствуйте, RikkiTikkiTavi, Вы писали:

RTT>Здравствуйте, gunf, Вы писали:


G>>Я пробовал без Idle — все равно 99 % проца.

G>>Жду компоненту — могет там как-то подругому сделано?

RTT>на сколько я понял — тормозит при генерации display list, а не при отрисовке (это разные вещи)



не пойму я тогда — он что display list постоянно генерирует? его нужно сгенерировать однажды, а потом — рисовать сколько угодно... тогда имхо можно не заботится об эффективности кода его генерации — это ведь один раз происходит. а тормозит у нас — всЁ время. значит рисование надо оптимизировать!
вообщем вот какой вопрос "на засыпку" я имею ввиду:
зависит ли скорость рисования display list-а от кода его создвшего? (если суть сцены одинакова)

vox clamantis in deserto
Re[7]: OpenGL - тормоза
От: RikkiTikkiTavi Россия  
Дата: 22.06.04 13:20
Оценка:
так и было, и не где-нибудь, а прям в OnIdle
Re: OpenGL - тормоза
От: Tuo_Bellas Россия  
Дата: 22.06.04 21:11
Оценка:
Здравствуйте, gunf, Вы писали:

G>Делаю 3D viewer на OpenGL и при наличии файла более 1.5 Мб (около 100 000 точек — рисую просто линии) — тормоза + 98% проца.

G>Что можно сделать?

Линии как раз рисовать медленно. Обычно одна линия -- один треугольник.

А вообще, отсекай невидимые и слишком далекие грани. Ключевые слова: frustum culling, quadtree, octtree и т.п.

Плюс используй везде где возможно вертексные буферы (стандартное расширение ARB_vertex_buffer_object, доступно с OpenGL 1.4) или, хотя бы, дисплейные списки.

Почитай FAQи по performance'у. Только не слишком древние.

HTH,
Tuo_Bellas.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.