简体   繁体   English

使用openGL进行常规窗口屏幕捕获

[英]Regular window screen capture using openGL

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. 使用窗口API(BitBlt或CImageClass)很容易,这不是我想要的方式。

I want do it using opengl. 我想用opengl来做。 so I found glReadPixel funtion and window TRANSPARENT. 所以我找到了glReadPixel函数和透明窗口。

But it just read pixel own Windows application screen.(Save as bmp file and check) 但是它只是读取像素自己的Windows应用程序屏幕。(另存为bmp文件并检查)

Initialize() 初始化()

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;

Roop 圆环

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. Q1。 Is it possible desktop capture(Full Image GPU output) with OPENGL? 使用OPENGL是否可以进行桌面捕获(全图像GPU输出)?

Q2. Q2。 If Q1 is possible, Should I use FBO and PBO GL_BACK?? 如果可以进行Q1,是否应该使用FBO和PBO GL_BACK?

Q3. Q3。 How to access to mother window or GPU adapter? 如何访问母窗口或GPU适配器? >> GL seems to strongly reject this.(I don't want any rendering, just read pixel data from GPU(Desktop image. not rendered by my application.)(If it is possible ...)) >> GL似乎强烈拒绝这一点。(我不需要任何渲染,只需从GPU读取像素数据(桌面图像。不由我的应用程序渲染。)(如果可能的话...))

Anybody shows to me about link or idea? 有人向我展示链接或想法吗?

What you're asking for is something completely outside the scope of OpenGL. 您要的东西完全超出了OpenGL的范围。 OpenGL is designed to be a platform-agnostic API for applications to talk about drawing stuff into framebuffers in an abstract fashion. OpenGL被设计为与平台无关的API,供应用程序讨论以抽象方式将内容绘制到帧缓冲区中。 OpenGL has no notion of windows*, screens, or a desktop. OpenGL没有Windows *,屏幕或桌面的概念。 OpenGL doesn't operate at a level where such concepts exist. OpenGL无法在存在此类概念的级别上运行。 Heck, OpenGL doesn't even know what a GPU is. 哎呀,OpenGL甚至都不知道GPU是什么。 OpenGL is supposed to be initialized through platform-specific mechanisms to establish a context which assigns actual meaning to OpenGL API calls. 应该通过特定于平台的机制来初始化OpenGL,以建立一个将实际含义分配给OpenGL API调用的上下文。 As far as I know, there is no way to set up an OpenGL context with a framebuffer whose contents would somehow correspond to the desktop on Windows (or any other platform I'm aware of). 据我所知,没有办法用帧缓冲区设置OpenGL上下文,该缓冲区的内容将以某种方式对应于Windows(或我知道的任何其他平台)上的桌面。 As far as my understanding goes, this wouldn't really make sense… 就我的理解而言,这真的没有道理……

To do what you want to do, you'll have to rely on the respective platform-specific APIs. 要完成您想做的事情,您将不得不依赖各自的平台特定的API。 The probably simplest way on Windows is to get an HDC for the entire desktop and BitBlt from there. Windows上最简单的方法可能是从那里获得整个桌面的HDC和BitBlt。 See, eg, this question for more on that. 有关更多信息,请参见此问题 A more modern approach would be to use the DXGI Desktop Duplication API . 一种更现代的方法是使用DXGI桌面复制API

(*) yes, I know the OpenGL specification technically does talk about "windows" in a few places; (*)是的,我知道OpenGL规范确实在一些地方谈到了“ windows”; but it only really does so when it's talking about all the things it's not responsible for… 但是只有在谈论所有不负责的事情时,它才这样做……

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. 使用窗口API(BitBlt或CImageClass)很容易,这不是我想要的方式。

But it's the way it's supposed to be done. 但这是应该完成的方式。

I want do it using opengl. 我想用opengl来做。 so I found glReadPixel funtion 所以我发现glReadPixel功能

You can't. 你不能 OpenGL doesn't "know" about the desktop, or other windows (or actually what windows are at all). OpenGL不会“了解”桌面或其他窗口(或实际上根本不是什么窗口)。 The function glReadPixels will work reliably only for images that have been drawn with OpenGL itself. glReadPixels函数仅对使用OpenGL本身绘制的图像可靠地起作用。

You can't use OpenGL to take screenshots! 您不能使用OpenGL截屏! On older computers it might seem to work, but that's only because of their older memory management where when you create a new window, its memory will be "cut" from what was below and if you read that, it looks like a way to make screenshots. 在较旧的计算机上,它似乎可以正常工作,但这仅是由于它们的较旧的内存管理,当您在其中创建新窗口时,其内存将被从下面的内容中“切出”,如果您阅读它,它看起来就像是一种制作方法屏幕截图。 But it is not. 但事实并非如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM