GUI: Sposób na rysowanie

Podczas pisania obsługi eventów wpadła mi do głowy pewna myśl. Mianowicie, zastanowiłem się po co rysować w każdej klatce całe GUI skoro i tak rzadko kiedy coś się tam zmienia.

A może by tak zrenderować GUI  do tekstury i wyświetlać tylko teksturę? Takie rozwiązanie znacznie zwiększyłoby wydajność rysowania takiego GUI. Nawet idąc na łatwiznę i odrysowując całe GUI gdy tylko jeden przycisk zmieni swój kolor bo myszka jest akurat nad nim zyskujemy całą masę przebiegów, w których jednak nic ciekawego się nie dzieje.

Pokombinuję z tym trochę i pochwalę się efektami bądź ich brakiem ^^

Napisane w Programowanie, Przemyślenia. Tagi: , .

Odpowiedzi: 13 do “GUI: Sposób na rysowanie”

  1. Xion mówi:

    Ciekawy pomysł. Ale ja bym buforował poszczególne ‘duże’ kontrolki - najlepiej okna. Poza tym gdyby jeszcze udało się wykryć, czy w danym zdarzeniu kontrolka faktycznie zmieniła swój wygląd, to rzeczywiście zysk na wydajności mógłby być spory. Być może do tego celu wystarczy sprawdzenie, czy zdarzenie w rodzaju Paint zostało obsłużone (ale to już zależy od szczegółów implementacji GUI).

    Jeśli jednak chodzi o rysowanie, to zalecałbym wydzielenie do tego osobnego modułu - tak, aby kontrolki nie wydawał poleceń w stylu ‘narysuj prostokąt’, ale raczej ‘narysuj w(y)ciśnięty przycisk’, ‘narysuj obwódkę zaznacenia’, itd. Takie rozwiązanie zrobiłem u siebie, przejmując je w z Windows Forms, i sprawdza się całkiem nieźle. Dodatkowo tutaj mamy kolejne miejsce na optymalizacje, jako że ten obrazek przycisku również można cache’ować do tekstury.

  2. Reg mówi:

    Też myślałem, żeby coś takiego sobie napisać. Ostatecznie zrezygnowałem, bo to jakby nie patrzeć tylko optymalizacja wydajności, a całkowicie zmienia koncepcję modułu GUI i jest bardzo trudna do napisania.

    Aha, jak będziesz to miał to możesz łatwo zrobić wyginające się, gumowe okienka jak w XGL :)

  3. moriturius mówi:

    Fakt - przekonałem się, że nie jest to proste zadanie. Jak na razie chyba dam sobie z tym spokój. Może później coś z tym wytworzę. (prawdę mówiąc wątpię ^^)

  4. REDZIK mówi:

    heh :P ale mam gdzieś takie GUI napisałem z co prawda nudów ale działa świetnie, na zasadzie rysowania na OPENGL TEXTURE ale co do rysowania uzyłem tej samej techniki MS i borland czyli rysowanie komponentów w pamięci na obrazek :D (coś jak canvas ) u mnie to sie nazywa Class’a TPen
    Tekstura OPENGL = jeden widet bazowy czyli np OKIENKO jak w Windowsie, reszta jest przerysowywana zależnie od potrzeb. Biblioteki wymagane: libpng , zlib, opengl, freetype, libjpeg. jak chcesz dam screen i demko

    wniosek program rysuje tylko 1 teksturę opengl :) i podmienia na niej grafikę kiedy chcemy….

    Pozdro Redzik (old sql developer)

  5. moriturius mówi:

    Redzik: thx, ale nie trzeba bo ja uzywam DirectX wiec nic by mi to nie pomoglo :)

  6. REDZIK mówi:

    DX :) tak po prawdzie to nie ma znaczenia czy uzywasz DX czy Gl czy tez libSDL, cały myk na tym polega, dam Ci screen’a : http://redzik.boo.pl/x/screen1a.png
    Jeśli nie klikam zednych elemętów na gui lub nie wymagają przerysowania to nie trace na to czasu i cennego procesora a co do karty graficznej jej zadaniem jest wyświetlenie jednej Textury :) a nie 100 elementów z których składa się gui jak widziałem w innych GUI, dodatkowo to jest zajebiście szybkie troszke ASM wsadziłem w kod :)

    kontrolki które są juz napisane: Window, Listbox, Inputbox, TextArea (ni ma scroola V i H ), Label, Button, Slider, PageControl, CheckBox, ImageObiect, CpuMonitor… dalej mi sie nie chciało robić, na podstawie Genettychnych mozna tworzyć następne, stworzenie kontrolki/stylu to kwestia kilku minut …
    Pozdro Redzik (old sql developer)

  7. moriturius mówi:

    Nie, no właśnie na tym cały mój pomysł polegał, żeby rysować GUI tylko wtedy kiedy coś się faktycznie zmieni.

    Jedynym problemem jest konkretna implementacja więc kod z OpenGL niewiele by pomógł.

    Zainteresowałeś mnie jednak tym: “na podstawie Genettychnych mozna tworzyć następne”.

    Co miałeś na myśli? Chętnie bym ten kod obejrzał ^^

  8. REDZIK mówi:

    Kodu związanego czysto OpenGL jest tyle:
    //– kod ——–
    int CTextureManager::BuildTex(int id, int gFilter, int inFilter,SDK_Surface * p )
    {
    if(id == (-1) ) id = GetNewTextureID (-1);

    glBindTexture ( GL_TEXTURE_2D, id );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D ( GL_TEXTURE_2D, 0 ,
    gFilter ,
    p->nPowWidth ,
    p->nPowHeight,
    0 ,
    inFilter ,
    GL_UNSIGNED_BYTE,
    p->Data
    );
    return id;
    }
    //– kod ——–
    Oczywiście funkcja przebudowania GL_TEXTURE tez jest przebudowywana tylko w razie potrzeby….
    no i jeszcze wyświetlenie grafiki :) ale to nie ma związku z gui, co do genetycznych, chodzi o to ze podwędziłem sposób jaki zastosowali w delphi wszystkie komponenty posiadają cechy główne czyli: rysowanie , akcje klawiszowe, pozycje, aktywna kontrolka, martwa kontrolka… na podstwie tych cech mozna stworzyć uniwersalny obiekt kontrolki i metodami Virtual’nymi połączyć go z nowym komponentem… ogólnie chodzi o to ze mozna zrobić wszystkie kontrolki takie jakie ma winda (do piekła) czy Linux wszystko to kwestia fantazji :) dodatkowo w np: TextArea mozna dodać nowe wewnętrzne kontrolki, czyli np: paski przewijania na podstawie kontrolek juz istniejących takich jak Slider (ale to by chyba było głupawym pomysłem)

    mały załącznik do wypowiedzi :
    Class’a główna Widget:
    http://redzik.boo.pl/x/a1.txt
    przykładowa kontrolka button: (kod całej kontrolki)
    http://redzik.boo.pl/x/a2.txt

    Wprawdzie zasada działania GUI i komponentów ( gadżetów ) to żadne odkrycie ale fajnie jest to samemu napisać. Jest jeszcze Główny “zbiornik” nazwałem go GUI_BASE, to tam przypisujemy przypisujemy wszystkie dane wejściowe on zarządza całym rysowaniem wszystkiego, rozdzielaniem Eventów (klawisze mysz) na poszczególne kontrolki i innymi takimi dziwactwami.

    cały kod do napisania w naszej aplikacji to:
    //— KOD —

    GUI_Base * myGUI = new GUI_Base();
    SDK_Window * myWINDOW = new SDK_Window(0,0,450,580, false, true,”..:: łokienko :D ::..”,font);
    myWINDOW->setVisible(true);
    SDK_PushButton * btn = new SDK_PushButton(300, 64,50,22,”text” ,font );

    //btn->SetFunction( func_btn ); // Callback dla akcji

    myWINDOW->addWidget( btn ); // dodajemy kontrolke do rodzica

    myGUI ->WidgetsAddFirst( myWINDOW ); // dodajemy całe okienko do Głównego kontenera

    // potem gdzieś w kodze (ale ne byle gdzie):

    myGUI->Draw(); // rysowanie
    myGUI->UpdateEvents(); // aktualizacja zdarzeń

    //— KOD —

  9. moriturius mówi:

    “co do genetycznych, chodzi o to ze podwędziłem sposób jaki zastosowali w delphi”

    zupełnie nie rozumiem co w tym sposobie “genetycznego” ?
    ot zwykłe dziedziczenie i wykorzystanie polimorfizmu

  10. REDZIK mówi:

    no nie do konca o to mi chodzi chodzi mi bardziej o to ee coś w stylu o przykład:
    // ———————-
    class myBUTTON : public SDK_PushButton
    {
    myBUTTON ()// konstruktor
    {
    SetMyDraw(true); // rysowanie w kontrolce standardowej jest ignorowane O TO CHODZI
    };
    // ———————-
    Class myBUTTON jest nowa kontrolką na podstawie kontrolki GENETYCZNEJ (coś jak szablon, genetyczna czyli posiada cechy poprzednika ale nie wszystkie no i nowe oczywiście )… ni umiem tego inaczej wytłumaczyć

  11. moriturius mówi:

    Ale to się po chrześcijańsku nazywa właśnie dziedziczeniem, gdzie SDK_PushButton jest klasą bazową, a myBUTTON jest klasą pochodną.

    Określenie którejś z klas jako genetycznej jest dość oryginalne choć w pewnym sensie nawet pasuje ;)

  12. REDZIK mówi:

    eee głównie chodzi mi o to :
    //—–
    SetMyDraw(true); // rysowanie w kontrolce standardowej jest ignorowane O TO CHODZI
    //—–
    nie o dziedziczenie (choć tam tez jest to jedna z podstaw działania) ale oki mniejsza… :)

  13. moriturius mówi:

    czyli nie rozumiem co w tym genetycznego ^^

    ja jak chce zeby klasa pochodna rysowala po swojemu to po prostu nadpisuje metodę wirtualną render() i po sprawie :P

Napisz odpowiedź