OpenGL i renderowanie do bitmapy

0

Potrzebuję aby moja wyredenderowana scena mogła zostać wyswietlona na canvas.
Ale jednocześnie aby okno w którym jest renderowana scena nie było nigdzie widoczne.
Jak to zrobić ?

Jeżeli renderuję do panel.handle to jak skopiować to co jest wyświetlone w obszarze panelu do innej bitmapy albo canvas ?

Albo może renderowąć do tekstury ? I w ten sposób będzie szybciej ?

1

glReadPixels próbowałeś? Poza tym poczytaj o PBuffers.

0

Moja karta nie posiada WGL_ARB_pbuffer wiec pbuffer odpada w przedbiegach
ale to drugie wygląda interesująco.

0

Kawałek kodu poniżej, zrobiłem sobie prosty test szybkości 1000 powtórzeń:

[1] glReadPixels - wykonywało się 585ms

[2] przepisanie bufora do BMP 200ms

[3] Canvas.CopyRect trwa najdłużej 1454ms

**A jak by mozna było wyświetlać szybciej dane odczytane za pomocą glReadPixels ? **

procedure TForm001.btn4Click(Sender: TObject);
var
  b: TBitmap;
  mem: Pointer;
  mem1: PIntegerArray absolute mem;
  p1,p2: pointer;
  x,y: integer;
  i: integer;
  t1,t2: dword;
begin
 //Application.OnIdle := nil;
 //Timer1.Enabled := False;

  b := TBitmap.Create;
  b.PixelFormat := pf24bit;
  b.Width := Panel1.Width;
  b.Height := Panel1.Height;
  //

  GetMem(mem, b.Width * b.Height *3 );

  t1 := GetTickCount;
  for I := 0 to 1000 - 1 do
  begin
    // 585ms/1000
    glReadPixels(0,0, b.Width, b.Height, GL_BGR , GL_UNSIGNED_BYTE,mem);

    // 200ms/1000
    for y := 0 to b.Height - 1 do
    begin
      //p1 := b.ScanLine[b.Height -  y -1];
      p1 := b.ScanLine[y ];
      p2 := pbyte(mem) + b.Width * 3 * y;
      Move(p2^, p1^, b.Width*3  );
    end;

    // 1454ms/1000
    Canvas.CopyRect(Rect(0,0,b.Width,b.Height),b.Canvas ,Rect(0,0,b.Width,b.Height));
  end;

  t2 := GetTickCount;
  caption :=  ' Czas ms: '+IntToStr(t2  - t1)
             +' Transfer MB: '+ floattostr(b.Width * b.Height *3*1000 / (1024*1024) )
             +' Speed MB/S: '+ FloatToStr(b.Width * b.Height *3*1000 / (1024*1024) / ((t2  - t1) / 1000 ) ) ;



  b.SaveToFile('e.bmp'); // aby sobie pooglądać


  FreeMem(mem);
  b.Free;
end;
1

Strasznie duże te czasy masz. Może to wina Delphi? :P A bardziej na serio to może jednak tryb wyświetlania to nie 24 bity, ale np 32 z jednym bajtem nieużywanym? Upewnij się jakie masz formaty pikseli i kopiuj dane bez zmiany formatu.

0
Wibowit napisał(a)

Strasznie duże te czasy masz. Może to wina Delphi? :P A bardziej na serio to może jednak tryb wyświetlania to nie 24 bity, ale np 32 z jednym bajtem nieużywanym? Upewnij się jakie masz formaty pikseli i kopiuj dane bez zmiany formatu.

Nie napisałem jak duży obraz kopiuje ;)
I jak by ktoś czytał i nie był w temacie to czasy są podane dla 1000 powtórzeń danego fragmentu kodu
A tak serio o którym trybie wyświetlania mówimy ?
O trybie kolorów w windows ?
O PixelFormat bitmapy ?
O tym może :

  pfd.iPixelType:=PFD_TYPE_RGBA;      // PFD_TYPE_RGBA or PFD_TYPEINDEX
  pfd.cColorBits:=32;
  pfd.cDepthBits := 32;

?

Teraz sprawdziłem na innym komputerze ;) (wczesniej było Core 2 Duo teraz i7 (karty graf GF 9800GT)
I wyniki zgoła inne
[1]
glReadPixels 1754ms dla GL_BGR i 1652 GL_RGBA

[2] kopiowanie do BITMAP
406ms

[3]
Canvas.CopyRect 234ms dla pf32bit i 593ms pf24bit

Czyli Twoja teza żeby wszystko było 32 bitowe na pewno jest prawdziwa zastanawia mnie tylko co jest przyczyna różnic ?
BO jeszcze mam różne systemy operacyjne , na i7 jest "7"64bit a na starszym komputerze XP 32bit

0

Aj sorry, nie zauważyłem, że to 1000 powtórzeń :P
Szerokość adresów pamięci nie ma znaczenia (tzn czy system jest 32-bitowy, czy 64-bitowy). Liczy się format piksela. Teraz prawie wszędzie piksele są 32-bitowe - 3 kanały po 8 bitów plus 8 bitów nieużywane. Dzięki temu po pierwsze liczenie adresu jest szybsze (minimalnie) ale co najważniejsze, odczyt danych jest najszybszy jeżeli dane są wyrównane do potęgi dwójki nie mniejszej niż rozmiar danych. A więc dla 24-bit byłoby to 32-bit i oczywiście dla 32-bit też byłoby to 32-bit. Poza tym, tak jak pisałem, zmiana formatu danych też trochę trwa, zamiana z BGR na BGRA to dobrych kilka operacji na bajtach, wychodzi sporo instrukcji na bajt, pomnóż to razy ilość bajtów i wyjdzie ci dlaczego są różnice.

A tak serio o którym trybie wyświetlania mówimy ?
O trybie kolorów w windows ?
O PixelFormat bitmapy ?
O tym może :

Dla najwięszej wydajności w każdym z tych przypadków powinien być taki sam format piksela. Najlepiej najpierw pobierz format piksela z Windowsa, a potem utwórz Canvasa i okienko OpenGL z takim samym formatem piksela.

1 użytkowników online, w tym zalogowanych: 0, gości: 1