read back the rendered texture
now it should hold the whole normal map. In case you do not have Render to texture available (older Intel HD) you can render to screen instead and then just use glReadPixels
.
As you want to save this to image here a small VCL example of saving to 24 bit bmp:
//---------------------------------------------------------------------------
void screenshot(int xs,int ys) // xs,ys is GL screen resolution
{
// just in case your environment does not know basic programing datatypes
typedef unsigned __int8 BYTE;
typedef unsigned __int16 WORD;
typedef unsigned __int32 DWORD;
xs&=0xFFFFFFFC; // crop down resolution to be divisible by 4
ys&=0xFFFFFFFC; // in order make glReadPixel not crashing on some implementations
BYTE *dat,zero[4]={0,0,0,0};
int hnd,x,y,a,align,xs3=3*xs;
// allocate memory for pixel data
dat=new BYTE[xs3*ys];
if (dat==NULL) return;
// copy GL screen to dat
glReadPixels(0,0,xs,ys,GL_BGR,GL_UNSIGNED_BYTE,dat);
glFinish();
// BMP header structure
#pragma pack(push,1)
struct _hdr
{
char ID[2];
DWORD size;
WORD reserved1[2];
DWORD offset;
DWORD reserved2;
DWORD width,height;
WORD planes;
WORD bits;
DWORD compression;
DWORD imagesize;
DWORD xresolution,yresolution;
DWORD ncolors;
DWORD importantcolors;
} hdr;
#pragma pack(pop)
// BMP header extracted from uncompressed 24 bit BMP
const BYTE bmp24[sizeof(hdr)]={0x42,0x4D,0xE6,0x71,0xB,0x0,0x0,0x0,0x0,0x0,0x36,0x0,0x0,0x0,0x28,0x0,0x0,0x0,0xF4,0x1,0x0,0x0,0xF4,0x1,0x0,0x0,0x1,0x0,0x18,0x0,0x0,0x0,0x0,0x0,0xB0,0x71,0xB,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
// init hdr with 24 bit BMP header
for (x=0;x<sizeof(hdr);x++) ((BYTE*)(&hdr))[x]=bmp24[x];
// update hdr stuf with our image properties
align=0; // (4-(xs3&3))&3;
hdr.size=sizeof(hdr)+(ys*(xs3+align));
hdr.width=xs;
hdr.height=ys;
hdr.imagesize=ys*xs3;
// save BMP file (using VCL file functions exchange them with whatever you got)
hnd=FileCreate("screenshot.bmp"); // create screenshot image file (binary)
if (hnd!=-1) // if file created
{
FileWrite(hnd,&hdr,sizeof(hdr));// write bmp header
for (a=0,y=0;y<ys;y++,a+=xs3) // loop through all scan lines
{
FileWrite(hnd,&dat[a],xs3); // write scan line pixel data
if (align) // write scan line align zeropad if needed
FileWrite(hnd,zero,align);
}
FileClose(hnd); // close file
}
// cleanup before exit
delete[] dat; // release dat
}
//---------------------------------------------------------------------------
The only thing used from VCL are binary file access routines so just swap them with what you have at disposal. Now you can open this bmp in whatever image software and convert to whatever format you want like png... without the need to encode it yourself.
The bmp header structure was taken from this QA:
Also beware of using char/int
instead of BYTE/WORD/DWORD
it usually leads to data corruption for tasks like this if you do not know what you doing...