Précédent   Forum des professionnels en informatique > Applications > Développement 2D, 3D et Jeux > API graphiques > OpenGL
OpenGL Forum d'entraide sur le développement en OpenGL. Avant de poster -> FAQ OpenGL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 12/01/2012, 16h45   #1
Invité de passage
 
Inscription : avril 2010
Messages : 7
Détails du profil
Informations forums :
Inscription : avril 2010
Messages : 7
Points : 1
Points : 1
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 :
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
tyrahell est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2012, 19h40   #2
Membre éclairé
 
Avatar de TNT89
 
Inscription : juillet 2007
Messages : 288
Détails du profil
Informations personnelles :
Âge : 22

Informations forums :
Inscription : juillet 2007
Messages : 288
Points : 308
Points : 308
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...
TNT89 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 19h09.


 
 
 
 
Partenaires

Hébergement Web