|
Invité de passage
Inscription : avril 2010 Messages : 7 Détails du profil  Informations forums : Inscription : avril 2010 Messages : 7 Points : 1 Points : 1
|
FBO : offscreen-rendering : limitation mémoire
Bonjour à tous,
Je travail sur le développement d'un logiciel de calcul de structure permettant de visualiser les modèles sous OpenGL. J'essaie de mettre en place une méthode pour exporter un grand nombre d'image (+/- 1000) à une définition supérieure (1280*1024) à celle des fenêtres de mon application.
Pour ce faire j'ai implémenté les FBO dans mon application et cela fonctionnait avec l'algo suivant :
- Bind/Alloc Texture Buffer
- Bind/Alloc Depth Buffer
- Bind/Alloc FBO
- Bind Texture Buffer to FBO
- Bind Depth Buffer to FBO
- Select FBO to render
- Render Scene to FBO
- Read FBO Texture buffer
- Export to BMP
- Unbind/Delete all buffer
Le problème de cet algo c'est qu'après l'avoir fait bouclé +/- 200 fois, j'obtenais des glGetError de type OUT_OF_MEMORY, donc vraisemblablement, le driver travail salement la VRAM, la segmente et la rend inallouable
Qu'à cela ne tienne après quelques recherches j'ai pris le parti de mettre en place mes trois buffer (texture, depth & FBO) une bonne fois pour toute au lancement de l'appli et de travailler dedans sans bouclage allocation / désallocation.
Hélas avec cette méthode j'obtiens des résultats incomplets comme vous pouvez le voir sur les images suivantes :
Première image exportée :
197ème image exportée :
On voit nettement sur la seconde image que seul le cadran inférieur gauche est actualisé, comme si glreadpixel ne faisait pas la totalité du boulot.
De plus sur une suggestion d'un gars du forum OpenGL j'ai essayé de maximiser ma fenêtre et là le rendu off screen semble fonctionner faisant penser à un problème de viewport ou de cible de rendu : http://www.opengl.org/discussion_boa...567#Post308567
Hélas je retourne le problème dans tous les sens et je commence sérieusement à sécher, si vous aviez quelques minutes (voir plus pour les courageux) ça pourrait m’ôter l'aiguille du pied !
Je vous laisse ci-dessous les codes incriminés
Tips : Global byte *ReadBufferGL = (byte*) malloc(4096*4096*3);
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| void CGLView::RenderSceneToFile()
{
// Find Max definition of GC
GLint var;
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &var);
if ( var > 4096 )
{
var = 4096;
}
if( hsize_export > var || vsize_export > var )
{
CString MyMessage = "Definition maximale autorisée : ";
MyMessage.Format("%s%i",MyMessage,var);
AfxMessageBox(MyMessage);
hsize_export = var;
vsize_export = var;
RenderFailed = 1;
}
else
{
if( AllocateFBO == 0 )
{
// create a texture object to store color info
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); //GL_LINEAR
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, hsize_export, vsize_export, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0);
// create a renderbuffer object to store depth info
glGenRenderbuffersEXT(1, &rboId);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,hsize_export,vsize_export);
// create a framebuffer object
glGenFramebuffersEXT(1, &fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
// attach the texture to FBO color attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, textureId, 0);
// attach the renderbuffer to depth attachment point
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, rboId);
AllocateFBO = 1;
}
// check FBO status
GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
if( status != GL_FRAMEBUFFER_COMPLETE_EXT )
{
VerboseFBO(status);
RenderFailed = 1;
}
else
{
float save_m_height = m_height;
float save_m_width = m_width;
m_height = vsize_export;
m_width = hsize_export;
float MyRed = (float)bg_red_export / (float)255;
float MyGreen = (float)bg_green_export / (float)255;
float MyBlue = (float)bg_blue_export / (float)255;
glClearColor( MyRed, MyGreen, MyBlue, 0.5f );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
RenderSceneToOffScreen();
RenderFBOToFile();
m_height = save_m_height;
m_width = save_m_width;
glClearColor(m_color[BACKGROUND][0], m_color[BACKGROUND][1], m_color[BACKGROUND][2], 0.5f);
}
}
} |
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| void CGLView::RenderSceneToOffScreen()
{
m_bBlackElement = 31337;
// Renderscene pour opengl
glLoadIdentity();
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
SetPers(true);
//Position de la scene
glLoadIdentity();
glPushMatrix();
PanZoomRotate();
glEnable(GL_DEPTH_TEST);
BuildFont(m_CharSize);
//Affichage des elements
if( m_nType == 1 || m_nType == 2 )
{
RenderPrimitiv( 0, NLIST );
}
if(m_nType == 3)
{
// Primitives classiques
RenderPrimitiv( 0, DIAG_N_MIN );
// Primitives DIAG & ISO MIN
RenderPrimitivMin( DIAG_N_MIN, SOUDURE );
RenderPrimitivMin( ISO_DA_DX_MIN, DEFPL_INF );
// Primitives DIAG & ISO MAX
RenderPrimitivMax( DIAG_N_MAX, RELACHEMENT_SELECTED );
RenderPrimitivMax( ISO_DA_DX_MAX, NLIST);
}
// Surcharge des elements en noir
if(m_Affiche[NOEUDS]){Dessine(NOEUDS);}
if(m_Affiche[NUMEROS_NOEUDS]){Dessine(NUMEROS_NOEUDS);}
if(m_Affiche[ELEMENTS]){Dessine(ELEMENTS);}
if(m_bValNum)
{
if(m_nType==2)
{
for(int i=DIAG_N;i<DIAG_CABLES;i++)
if(m_Affiche[i])
Dessine(i);
}
if(m_nType==3)
{
for(int i=DIAG_N_MIN;i<DIAG_N_MAX;i++)
if(m_Affiche[i] && m_AfficheMin)
Dessine(i);
for(int i=DIAG_N_MAX;i<NLIST;i++)
if(m_Affiche[i] && m_AfficheMax)
Dessine(i);
}
}
//pop pour PanZoomRotate
glPopMatrix();
if(m_bSelectMode && m_nSelectMode ==3 && m_state == PAN)
{
float x1,y1,x2,y2;
MouseToGL(m_CurrentPoint,x1,y1);
MouseToGL(m_Anchor,x2,y2);
glColor3f(1.0f,1.0f,1.0f);
glBegin(GL_LINE_LOOP);
glVertex2f(x1,y1);glVertex2f(x2,y1);
glVertex2f(x2,y2);glVertex2f(x1,y2);
glEnd();
}
glDisable(GL_DEPTH_TEST);
SetPers(false);
//dessin des axes
glPushMatrix();
glTranslatef(m_xmin+(m_xmax-m_xmin)*0.10,m_ymin+(m_ymax-m_ymin)*0.10,1.0f);
glRotatef(m_rotx, 1.0f, 0.0f, 0.0f);
glRotatef(m_roty, 0.0f, 1.0f, 0.0f);
float facteurZoom = (m_xmax-m_xmin) * 0.02;
glScalef(facteurZoom,facteurZoom,facteurZoom);
DrawAxisOffScreen();
glPopMatrix();
// Affichage échelle ISO
if(m_AfficheIso)
{
if(m_pIsocoul!=NULL)
{
IsoEchelleOffScreen(m_pIsocoul);
}
}
if(m_AfficheDiag)
{
LegendeDiag();
}
if(m_Affiche[CHARGES])
{
LegendeCharges();
}
if(m_nTit >0)
{
AfficheTitreOffScreen();
}
glFlush();
m_bBlackElement = 1337;
} |
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| void CGLView::SetPers(bool isModel)
{
//Pour éviter une division par 0, les hauteurs et largeur
//sont minimum 1
if(m_height <= 0) m_height = 1.f;
if(m_width <= 0) m_width = 1.f;
glViewport(0, 0, m_width, m_height);
//on réinitialise la matrice de projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float ratio = m_width/m_height;
float zDim = m_zoom * 2.f;
if(isModel && !m_bVueOrtho)
{
//perspective déformée -> angle de vue de 40 degré
//gluPerspective(40, ratio, 0.01f, m_maxdim*8.f);
gluPerspective(40, ratio, 1.0f, m_maxdim*8.f);
}
else
{
//on a le rapport dim = 1 (affichage écran sur le maximum pour zoom 1)
//et m_maxdim/2.f (affichage écran pour m_zoom 1)
if(m_longueur >= m_hauteur)
{
float dim = 1.f; //m_longueur/2.f;
m_xmax = dim;
m_ymax = dim/ratio;
}
else
{
float dim = 1.f; //m_hauteur/2.f;
m_xmax = dim*ratio;
m_ymax = dim;
}
m_xmin = -m_xmax;
m_ymin = -m_ymax;
if(isModel)
{
glOrtho(m_xmin, m_xmax, m_ymin, m_ymax, -zDim*4, (m_maxdim+zDim)*4 );
}
else
{
glOrtho(m_xmin, m_xmax, m_ymin, m_ymax, -40.f, 40.f);
}
}
glMatrixMode(GL_MODELVIEW); // Select the modelview matrix
glLoadIdentity(); // Reset the modelview matrix
} |
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| void CGLView::RenderFBOToFile()
{
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadPixels( 0, 0, hsize_export , vsize_export , GL_BGR, GL_UNSIGNED_BYTE, ReadBufferGL );
FILE *file = NULL;
fopen_s( &file, path_export, "wb" );
// Create & configure Bitmap and File info headers
BITMAPFILEHEADER bitmapFileHeader;
BITMAPINFOHEADER bitmapInfoHeader;
bitmapFileHeader.bfType = 0x4D42; //"BM" pour BMP
bitmapFileHeader.bfSize = vsize_export * hsize_export * 3;
bitmapFileHeader.bfReserved1 = 0;
bitmapFileHeader.bfReserved2 = 0;
bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biWidth = hsize_export ;
bitmapInfoHeader.biHeight = vsize_export ;
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biBitCount = 24;
bitmapInfoHeader.biCompression = BI_RGB;
bitmapInfoHeader.biSizeImage = 0;
bitmapInfoHeader.biXPelsPerMeter= 0; // ?
bitmapInfoHeader.biYPelsPerMeter= 0; // ?
bitmapInfoHeader.biClrUsed = 0;
bitmapInfoHeader.biClrImportant = 0;
fwrite(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, file);
fwrite(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, file);
fwrite(ReadBufferGL, vsize_export*hsize_export*3, 1, file);
fclose(file);
} |
Désolé pour le wall of text et en espérant qu'une âme charitable me sorte du bourbier
Cordialement,
Tyrahell
|