遊戲中需要截屏功能,GL中也有提供讀取像素數據的API
glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
傳入相關參數,然後傳入像素數據指針,就可以從綁定的顏色緩衝區中讀取出來像素數據,然後通過FreeImage或者其他方式,存儲爲圖片文件。
在上一篇的基礎上,從FBO的顏色附着上,即紋理,即顏色緩衝區中讀取像素數據。
轉自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
在第一次繪製之後,添加代碼
virtual void render()
{
if (m_width == 0 || m_height == 0)
{
return;
}
glBindRenderbuffer(GL_RENDERBUFFER, m_depthRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthRenderBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);
//用作紋理的顏色緩衝區,glReadPixels從這個顏色緩衝區中讀取
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
GLenum tmpStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (tmpStatus == GL_FRAMEBUFFER_COMPLETE)
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glViewport(0, 0, m_width, m_height);
{
//model;
glm::mat4 model = glm::mat4(1.0f);
//View
glm::mat4 view = glm::lookAt(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
//透視
glm::mat4 proj = glm::perspective(glm::radians(60.0f), 1.0f, 0.3f, 1000.0f);
proj = proj*view*model;
m_program.begin();
{
glm::vec3 pos[] =
{
glm::vec3(-5.0f, -5.0f, 0.0f),
glm::vec3(5.0f, -5.0f, 0.0f),
glm::vec3(0.0f, 5.0f, 0.0f),
};
glm::vec4 color[] =
{
glm::vec4(colorX, colorY, colorZ, 1),
glm::vec4(colorZ, colorX, colorY, 1),
glm::vec4(colorY, colorZ, colorX, 1),
};
colorX += 0.001f;
if (colorX > 1) colorX = 0;
colorY += 0.002f;
if (colorY > 1) colorY = 0;
colorZ += 0.003f;
if (colorZ > 1) colorZ = 0;
glUniformMatrix4fv(m_program.m_mvp, 1, false, &proj[0][0]);
glVertexAttribPointer(m_program.m_position, 2, GL_FLOAT, false, sizeof(glm::vec3), pos);
glVertexAttribPointer(m_program.m_color, 4, GL_FLOAT, false, sizeof(glm::vec4), color);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
m_program.end();
}
int tmpPixelSize = m_textureWidth*m_textureHeight * 4;
char* tmpPixelsBuffer = (char*)malloc(tmpPixelSize);
//從顏色緩衝區中讀取數據
glReadPixels(0, 0, m_textureWidth, m_textureHeight,GL_RGBA, GL_UNSIGNED_BYTE, tmpPixelsBuffer);
for (size_t i = 0; i < tmpPixelSize; i+=4)
{
tmpPixelsBuffer[i] ^= tmpPixelsBuffer[i + 2] ^= tmpPixelsBuffer[i] ^= tmpPixelsBuffer[i + 2];
}
SavePng(tmpPixelsBuffer);
free(tmpPixelsBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, m_texture);
......
......
}
}
讀取出來數據後,就可以通過FreeImage保存爲圖片文件
void SavePng(char* varPixelBuffer)
{
FIBITMAP* tmpFIBitMap = FreeImage_Allocate(m_textureWidth, m_textureHeight, 32, 8, 8, 8);
for (size_t y = 0; y < FreeImage_GetHeight(tmpFIBitMap); y++)
{
BYTE* tmpBIT = FreeImage_GetScanLine(tmpFIBitMap, y);
for (size_t x = 0; x < FreeImage_GetWidth(tmpFIBitMap); x++)
{
tmpBIT[0] = varPixelBuffer[(y*m_textureWidth + x) * 4 + 0];
tmpBIT[1] = varPixelBuffer[(y*m_textureWidth + x) * 4 + 1];
tmpBIT[2] = varPixelBuffer[(y*m_textureWidth + x) * 4 + 2];
tmpBIT[3] = 255;
tmpBIT += 4;
}
}
bool bSuccess = FreeImage_Save(FIF_PNG, tmpFIBitMap, "Screen.png", PNG_DEFAULT);
FreeImage_Unload(tmpFIBitMap);
}
轉自http://blog.csdn.net/huutu http://www.thisisgame.com.cn保存後的效果
示例工程下載:
http://pan.baidu.com/s/1gfMD2fT 提取碼a7q3