Hi Carsten !
I’ve modify argument 3 and 4 of glReadPixel but it change nothing.
Since 4 hour i’m working about your glviewport() thought.
I have supposed that if i do something wrong between my screen and off screen rendering and viewport, if i maximize my application on my dual screen i should have a full render in my color buffer and BASINGA it’s true, my color render buffer seems relative to the size of the application windows…
Well, the problem is that i can’t explain why, please can someone check my code if you find someting relevant inside ?
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);
}
}
}
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_bSelectMode )
{
if(m_Affiche[ELEMENTS] || m_Affiche[SECTIONS_WIRE] || m_Affiche[SECTIONS_FULL])
{
Dessine(ELEMENTS);
}
if(m_Affiche[CABLES])Dessine(CABLES);
if(m_Affiche[DALLES_PLEINES] || m_Affiche[DALLES_CONTOUR])Dessine(DALLES_PLEINES);
if(m_nType ==2)
{
if(m_Affiche[ELEMENTS_DEF] || m_Affiche[SECTIONS_WIRE_DEF] || m_Affiche[SECTIONS_FULL_DEF])
Dessine(ELEMENTS_DEF);
if(m_Affiche[CABLES_DEF])
Dessine(CABLES_DEF);
if(m_Affiche[DALLES_PLEINES_DEF] || m_Affiche[DALLES_CONTOUR_DEF])
Dessine(DALLES_PLEINES_DEF);
}
}*/
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();
// Ici que lon affiche l echelle d isocouleur
// surement ici quil faut tester m_bimpose
// afin de voir si on doit ou non recalculer les bornes d isocouleurs
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;
}
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);
}
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
}
Best regards ,
Tyrahell