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
Partager