OpenGL学习笔记:截图生成图片

获得窗口数据

  • 利用glReadPixels得到屏幕的像素值
  • 然后利用glTexImage2D获得GPU中的纹理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GLuint CaptureScreen(int width, int height, std::function<void()> foo)
{
foo();
unsigned char * screenPixel = new unsigned char[width*height*3];
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screenPixel);
GLuint texture;
//generate an opengl texture
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
//operation on current texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, screenPixel);
glBindTexture(GL_TEXTURE_2D, 0);
delete screenPixel;
return texture;
}

使用获得的窗口图像

  • 如果想直接显示,就把这个texture赋值给某个sprite
1
2
3
4
5
6
Texture*screenTexture = new Texture;
screenTexture->mTextureID = CaptureScreen(viewportWidth, viewportHeight, []()->void
{
RenderOneFrame(0.0f); // 这里是真实的draw,也是CaptureScreen的参数foo
});
sprite.SetTexture(screenTexture);
  • 保存为图片文件
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
SaveScreenPixelToFile(viewportWidth, viewportHeight, []()->void
{
RenderOneFrame(0.0f);
}, "screenshot.bmp");

//==============================================================

void SaveScreenPixelToFile(int width, int height, std::function<void()> foo, const char*filePath)
{
foo();
unsigned char * screenPixel = new unsigned char[width*height * 3];
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screenPixel);

FILE*pFile = fopen(filePath, "wb");
if (pFile)
{
BITMAPFILEHEADER bfh;
memset(&bfh, 0, sizeof(BITMAPFILEHEADER));
bfh.bfType = 0x4D42; //0x4D42="BM",是Bitmap文件的标志。
bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + width*height * 3;
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, pFile);

BITMAPINFOHEADER bih;
memset(&bih, 0, sizeof(BITMAPINFOHEADER));
bih.biWidth = width;
bih.biHeight = height;
bih.biBitCount = 24;
bih.biSize = sizeof(BITMAPINFOHEADER);
fwrite(&bih,sizeof(BITMAPINFOHEADER),1,pFile);

//rgb -> bgr
for (int i = 0; i < width*height * 3; i += 3)
{
unsigned char temp = screenPixel[i];
screenPixel[i] = screenPixel[i + 2];
screenPixel[i + 2] = temp;
}
fwrite(screenPixel, 1, width*height * 3, pFile);
fclose(pFile);
}
}

Scissor

  • 这个API是用来控制哪里可以绘制的,参数定义了一个矩形,矩形之外不会被绘制。
1
2
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, viewportWidth/2, viewportHeight);

glFlush

  • 驱动中的指令刷到显卡,并没有绘制完,没有返回。

glFinish

  • 发出的所有OpenGL指令执行完,并且返回了。但是画面不一定绘制出来,还在显存中。要等SwapBuffers后才显示。
# OpenGL
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×