使用 openGL 的常规 window 屏幕截图
Regular window screen capture using openGL
我正在尝试捕获我的桌面图像。 (所有图像,包括桌面输出到显示器)
使用 window API(BitBlt 或 CImageClass)很容易,但这不是我想要的方式。
我想用 opengl 来做。所以我发现 glReadPixel 函数和 window TRANSPARENT.
但它只是读取像素自己的 Windows 应用程序屏幕。(另存为 bmp 文件并检查)
初始化()
glfwSetErrorCallback(errorCallback);
if (!glfwInit()) {
std::cerr << "Error: GLFW " << std::endl;
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_DEPTH_BITS, 16);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, 4);
const int Monitor_count = GetMonitors();
GLwindow = glfwCreateWindow(
nWidth, // width
nHeight, // height
"OpenGL_Test", // window title
NULL, NULL);
if (!GLwindow) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSwapInterval(1);
if (glfwGetWindowAttrib(GLwindow, GLFW_TRANSPARENT_FRAMEBUFFER))
{
//...
}
glfwSetWindowOpacity(GLwindow, 0.0f);
auto Mode = glfwGetVideoMode(Monitor[0]);
glfwMakeContextCurrent(GLwindow);
glfwSetKeyCallback(GLwindow, keyCallback);
glewExperimental = GL_TRUE;
GLenum errorCode = glewInit();
if (GLEW_OK != errorCode) {
std::cerr << "Error: GLEW - " << glewGetErrorString(errorCode) << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
if (!GLEW_VERSION_3_3) {
std::cerr << "OpenGL 3.3 API is not available." << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glViewport(0, 0, nWidth, nHeight);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
std::cerr << "Error: " << std::endl;
}
return true;
循环
while (!glfwWindowShouldClose(GLwindow)) {
Sleep(10);
glClearColor(0.0f, 0.3f, 0.3f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT);
unsigned char *image = (unsigned char*)malloc(sizeof(unsigned char)*nWidth*nHeight * 3);
glReadPixels(0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, image);
glfwPollEvents();
}
return true;
Q1。是否可以使用 OPENGL 进行桌面捕获(全图像 GPU 输出)?
Q2。如果 Q1 可以,我应该使用 FBO 和 PBO GL_BACK??
Q3。如何访问 mother window 或 GPU 适配器? >> GL似乎强烈反对这一点。(我不想要任何渲染,只是从GPU读取像素数据(桌面图像。不是我的应用程序渲染的。)(如果可能的话......))
有人向我展示 link 或想法吗?
您要求的是完全超出 OpenGL 范围的东西。 OpenGL 被设计为与平台无关 API,应用程序可以以抽象的方式讨论将内容绘制到帧缓冲区中。 OpenGL 没有 windows*、屏幕或桌面的概念。 OpenGL 不在存在此类概念的级别上运行。见鬼,OpenGL 甚至不知道 GPU 是什么。 OpenGL 应该通过特定于平台的机制进行初始化,以建立一个上下文,该上下文为 OpenGL API 调用分配实际含义。据我所知,无法使用帧缓冲区设置 OpenGL 上下文,其内容会以某种方式对应于 Windows(或我知道的任何其他平台)上的桌面。就我的理解而言,这真的没有意义......
要做您想做的事,您必须依赖各自平台特定的 API。 Windows 上最简单的方法可能是为整个桌面获取一个 HDC,并从那里获取 BitBlt。参见,例如,this question for more on that. A more modern approach would be to use the DXGI Desktop Duplication API.
(*) 是的,我知道 OpenGL 规范在技术上确实在一些地方讨论了 "windows";但它只有在谈论所有它不负责的事情时才真正这样做……
I'm trying to my desktop image capture. (All images, including the desktop output to the monitor)
It's easy using window API (BitBlt or CImageClass) and it's not the way I want.
但这是应该的方式。
I want do it using opengl. so I found glReadPixel funtion
你不能。 OpenGL 不“了解”桌面或其他 windows(或者实际上根本 windows 是什么)。函数 glReadPixels
仅适用于使用 OpenGL 本身绘制的图像。
您不能使用 OpenGL 截取屏幕截图! 在较旧的计算机上它似乎可以工作,但这只是因为它们较旧的内存管理,当您创建一个新的 window,它的内存将从下面的内容中“截断”,如果您阅读它,它看起来像是一种制作屏幕截图的方法。但事实并非如此。
我正在尝试捕获我的桌面图像。 (所有图像,包括桌面输出到显示器)
使用 window API(BitBlt 或 CImageClass)很容易,但这不是我想要的方式。
我想用 opengl 来做。所以我发现 glReadPixel 函数和 window TRANSPARENT.
但它只是读取像素自己的 Windows 应用程序屏幕。(另存为 bmp 文件并检查)
初始化()
glfwSetErrorCallback(errorCallback);
if (!glfwInit()) {
std::cerr << "Error: GLFW " << std::endl;
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_DEPTH_BITS, 16);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, 4);
const int Monitor_count = GetMonitors();
GLwindow = glfwCreateWindow(
nWidth, // width
nHeight, // height
"OpenGL_Test", // window title
NULL, NULL);
if (!GLwindow) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSwapInterval(1);
if (glfwGetWindowAttrib(GLwindow, GLFW_TRANSPARENT_FRAMEBUFFER))
{
//...
}
glfwSetWindowOpacity(GLwindow, 0.0f);
auto Mode = glfwGetVideoMode(Monitor[0]);
glfwMakeContextCurrent(GLwindow);
glfwSetKeyCallback(GLwindow, keyCallback);
glewExperimental = GL_TRUE;
GLenum errorCode = glewInit();
if (GLEW_OK != errorCode) {
std::cerr << "Error: GLEW - " << glewGetErrorString(errorCode) << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
if (!GLEW_VERSION_3_3) {
std::cerr << "OpenGL 3.3 API is not available." << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glViewport(0, 0, nWidth, nHeight);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
std::cerr << "Error: " << std::endl;
}
return true;
循环
while (!glfwWindowShouldClose(GLwindow)) {
Sleep(10);
glClearColor(0.0f, 0.3f, 0.3f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT);
unsigned char *image = (unsigned char*)malloc(sizeof(unsigned char)*nWidth*nHeight * 3);
glReadPixels(0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, image);
glfwPollEvents();
}
return true;
Q1。是否可以使用 OPENGL 进行桌面捕获(全图像 GPU 输出)?
Q2。如果 Q1 可以,我应该使用 FBO 和 PBO GL_BACK??
Q3。如何访问 mother window 或 GPU 适配器? >> GL似乎强烈反对这一点。(我不想要任何渲染,只是从GPU读取像素数据(桌面图像。不是我的应用程序渲染的。)(如果可能的话......))
有人向我展示 link 或想法吗?
您要求的是完全超出 OpenGL 范围的东西。 OpenGL 被设计为与平台无关 API,应用程序可以以抽象的方式讨论将内容绘制到帧缓冲区中。 OpenGL 没有 windows*、屏幕或桌面的概念。 OpenGL 不在存在此类概念的级别上运行。见鬼,OpenGL 甚至不知道 GPU 是什么。 OpenGL 应该通过特定于平台的机制进行初始化,以建立一个上下文,该上下文为 OpenGL API 调用分配实际含义。据我所知,无法使用帧缓冲区设置 OpenGL 上下文,其内容会以某种方式对应于 Windows(或我知道的任何其他平台)上的桌面。就我的理解而言,这真的没有意义......
要做您想做的事,您必须依赖各自平台特定的 API。 Windows 上最简单的方法可能是为整个桌面获取一个 HDC,并从那里获取 BitBlt。参见,例如,this question for more on that. A more modern approach would be to use the DXGI Desktop Duplication API.
(*) 是的,我知道 OpenGL 规范在技术上确实在一些地方讨论了 "windows";但它只有在谈论所有它不负责的事情时才真正这样做……
I'm trying to my desktop image capture. (All images, including the desktop output to the monitor)
It's easy using window API (BitBlt or CImageClass) and it's not the way I want.
但这是应该的方式。
I want do it using opengl. so I found glReadPixel funtion
你不能。 OpenGL 不“了解”桌面或其他 windows(或者实际上根本 windows 是什么)。函数 glReadPixels
仅适用于使用 OpenGL 本身绘制的图像。
您不能使用 OpenGL 截取屏幕截图! 在较旧的计算机上它似乎可以工作,但这只是因为它们较旧的内存管理,当您创建一个新的 window,它的内存将从下面的内容中“截断”,如果您阅读它,它看起来像是一种制作屏幕截图的方法。但事实并非如此。