IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

FBO : offscreen-rendering : limitation mémoire


Sujet :

OpenGL

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 10
    Points : 9
    Points
    9
    Par défaut 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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  2. #2
    Membre confirmé Avatar de TNT89
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Âge : 34

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Points : 615
    Points
    615
    Par défaut
    Bonjour tyrahell,
    Citation Envoyé par tyrahell Voir le message
    un grand nombre d'image (+/- 1000) à une définition supérieure (1280*1024) à celle des fenêtres de mon application.
    Alors, la resolution des fenetres de ton application ne devrait avoir aucune incidence sur tes FBO (si le code est bon)... Ensuite, tu alloues totalement les 3.7Go de memoire nécessaire sur ton GPU? Ou tu fais frame par frame?
    Citation Envoyé par tyrahell Voir le message
    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.
    Mais bien sûr, tout le problème vient du driver... sauf qu'on ne fait JAMAIS d'allocation/desallocation dans la boucle de travail!


    Edit :
    Il n'y a pas d'unbind du FBO à la fin du rendu, ni de demande de régénération des mipmaps de la texture, avec d'abord un bind de la texture, puis glGenerateMipmapEXT(GL_TEXTURE_2D);.

    Après cette étape, il faut appeler glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptr); pour récupérer la texture.

    Dans la structure, je ne comprends pas pour quoi tu ne fais pas une fonction d'allocation (ou un constructeur) et une fonction de nettoyage ni le but logique de chaque fonction... OpenGL est une machine à état qui a tendance à être complexe à utiliser lorsque l'on commence à mélanger le code...

Discussions similaires

  1. Rendu CDialog en mémoire (offscreen rendering)
    Par vdaanen dans le forum MFC
    Réponses: 8
    Dernier message: 31/03/2009, 12h37
  2. Limite mémoire du Framework
    Par __JP__ dans le forum Framework .NET
    Réponses: 14
    Dernier message: 02/10/2007, 21h40
  3. Limites mémoire de ASE 12.5.4 sur windows 32 bit
    Par sybcat dans le forum Adaptive Server Enterprise
    Réponses: 1
    Dernier message: 10/08/2007, 08h51
  4. [ImageMagick] Limitations mémoire : juste une idée farfelue
    Par knoodrake dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 06/07/2007, 22h09
  5. Limite mémoire Windows XP Sp2
    Par DUBUIS dans le forum Windows
    Réponses: 2
    Dernier message: 07/07/2006, 12h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo