2013-05-12 8 views
5

Próbuję wykonać renderowanie OpenGL ES 2.0 do pliku obrazu, niezależnie od renderowania wyświetlanego na ekranie użytkownikowi. Obraz, który renderuję, ma inny rozmiar niż ekran użytkownika. Potrzebuję tylko tablicy bajtowej danych GL_RGB. Jestem zaznajomiony z glReadPixels, ale nie sądzę, że w tym przypadku byłaby to dobra sztuczka, ponieważ nie wyciągam z już renderowanego ekranu użytkownika.Renderowanie OpenGL ES 2.0 do obrazu

Pseudokod:

// Switch rendering to another buffer (framebuffer? renderbuffer?) 

// Draw code here 

// Save byte array of rendered data GL_RGB to file 

// Switch rendering back to user's screen. 

Jak mogę to zrobić bez przerywania wyświetlacz użytkownika? Wolałbym nie migotać ekranu użytkownika, rysując żądane informacje dla pojedynczej klatki, glReadPixel-ing, a następnie znikając.

Ponownie, nie chcę, aby pokazywał cokolwiek użytkownikowi. Oto mój kod. Nie działa. Czy coś mi brakuje?

unsigned int canvasFrameBuffer; 
bglGenFramebuffers(1, &canvasFrameBuffer); 
bglBindFramebuffer(BGL_RENDERBUFFER, canvasFrameBuffer); 
unsigned int canvasRenderBuffer; 
bglGenRenderbuffers(1, &canvasRenderBuffer); 
bglBindRenderbuffer(BGL_RENDERBUFFER, canvasRenderBuffer); 
bglRenderbufferStorage(BGL_RENDERBUFFER, BGL_RGBA4, width, height); 
bglFramebufferRenderbuffer(BGL_FRAMEBUFFER, BGL_COLOR_ATTACHMENT0, BGL_RENDERBUFFER, canvasRenderBuffer); 

unsigned int canvasTexture; 
bglGenTextures(1, &canvasTexture); 
bglBindTexture(BGL_TEXTURE_2D, canvasTexture); 
bglTexImage2D(BGL_TEXTURE_2D, 0, BGL_RGB, width, height, 0, BGL_RGB, BGL_UNSIGNED_BYTE, 0); 
bglFramebufferTexture2D(BGL_FRAMEBUFFER, BGL_COLOR_ATTACHMENT0, BGL_TEXTURE_2D, canvasTexture, 0); 

Matrix::matrix_t identity; 
Matrix::LoadIdentity(&identity); 
bglClearColor(1.0f, 1.0f, 1.0f, 1.0f); 
bglClear(BGL_COLOR_BUFFER_BIT); 
Draw(&identity, &identity, this); 
bglFlush(); 
bglFinish(); 

byte *buffer = (byte*)Z_Malloc(width * height * 4, ZT_STATIC); 
bglReadPixels(0, 0, width, height, BGL_RGB, BGL_UNSIGNED_BYTE, buffer); 
SaveTGA("canvas.tga", buffer, width, height); 
Z_Free(buffer); 

// unbind frame buffer 
bglBindRenderbuffer(BGL_RENDERBUFFER, 0); 
bglBindFramebuffer(BGL_FRAMEBUFFER, 0); 
bglDeleteTextures(1, &canvasTexture); 
bglDeleteRenderbuffers(1, &canvasRenderBuffer); 
bglDeleteFramebuffers(1, &canvasFrameBuffer); 
+0

znalazłem pewne informacje na temat renderowania-do -tekstury, ale nie jestem pewien, czy tego chcę, ponieważ chcę renderować do te tablica do zapisywania/analizowania danych obrazu. Ciekawi mnie, jaka jest właściwa ścieżka. – user1054922

+1

Określa, czy bufor kończy się na ekranie, czy nie, GPU nadal musi go renderować. Nie ma sposobu, aby renderowanie poza ekranem nie wpłynęło na wydajność ... –

+0

Nie mówię o wpływie na wydajność, mówię o tym, że nic nie pokazywałem użytkownikowi (np. Migotanie) – user1054922

Odpowiedz

4

Oto rozwiązanie dla każdego, kto potrzebuje go:

// Create framebuffer 
unsigned int canvasFrameBuffer; 
glGenFramebuffers(1, &canvasFrameBuffer); 
glBindFramebuffer(GL_RENDERBUFFER, canvasFrameBuffer); 

// Attach renderbuffer 
unsigned int canvasRenderBuffer; 
glGenRenderbuffers(1, &canvasRenderBuffer); 
glBindRenderbuffer(GL_RENDERBUFFER, canvasRenderBuffer); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, width, height); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, canvasRenderBuffer); 

    // Clear the target (optional) 
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 
glClear(GL_COLOR_BUFFER_BIT); 

    // Draw whatever you want here 

char *buffer = (char*)malloc(width * height * 3); 
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); 
SaveTGA("canvas.tga", buffer, width, height); // Your own function to save the image data to a file (in this case, a TGA) 
free(buffer); 

// unbind frame buffer 
glBindRenderbuffer(GL_RENDERBUFFER, 0); 
glBindFramebuffer(GL_FRAMEBUFFER, 0); 
glDeleteRenderbuffers(1, &canvasRenderBuffer); 
glDeleteFramebuffers(1, &canvasFrameBuffer); 
+0

Czy mógłbyś doradzić, co byś zrobił, gdyby szerokość/wysokość była większa niż GL_MAX_RENDERBUFFER_SIZE? Aby nie można było utworzyć bufora renderowania o żądanym rozmiarze ... – XZen

+0

Nie mogę uruchomić go na Linuksie. Czym są BGL_RGBA4, ZT_CACHE i Z_MALLOC, SAVE_TGA, Z_FREE? –

+0

Przepraszam, to są funkcje, które zbudowałem. Zmieniłem mój post, aby zastąpić go standardowymi odpowiednikami. – user1054922

1

Możesz renderować teksturę, czytać piksele i narysować kwadrat z tą teksturą (jeśli chcesz pokazać to użytkownikowi). Nie powinno migotać, ale oczywiście pogarsza wydajność.

iOS na przykład:

+0

Zaktualizowany post z jakimś kodem próbuję renderować teksturę poza ekranem. – user1054922

+0

Zaktualizowałem moją odpowiedź z kilkoma powiązanymi pytaniami z odpowiedziami na stackoverflow. – Trax

+0

Nie widzę połączenia z buforem glBindFrame, czy jest ono w wersji Draw? – Trax