0

问题总结:

我使用 OpenGL glReadPixels 来获取屏幕截图,但缓冲区没有改变。如果我使用 glGetError 从最后一个函数中获取错误,它返回 0,好像一切都很好。

我已经在网上进行了彻底的研究,没有发现任何人面临这样的问题。

详细说明:

我正在使用 CsGL.dll,它基本上只是将 OpenGL 包装到 C#,并且我已经进行了使用 GL 所需的初始化:来自 hWnd 的 DC,ChoosePixelFormat for DC 使用 PixelFormatDescriptor 并将其设置为它的格式,为 DC 创建 RC并调用 wglMakeCurrent(RC, DC)。


请注意,我正在为 Windows API 函数使用简单的包装器。这是我使用的初始化代码:

public unsafe void Init(IntPtr hWnd)
{
        this.DC = (IntPtr)User.GetDC(this.HWnd = hWnd);

        var pfd = new PIXELFORMATDESCRIPTOR();
        var sizeOf = Marshal.SizeOf(pfd);

        Kernel.ZeroMemory(new IntPtr(&pfd), sizeOf);
        pfd.nSize = (short)sizeOf;
        pfd.nVersion = 1;
        pfd.dwFlags = (int)(PixelFormatDescriptorFlagsEnum.PFD_DRAW_TO_WINDOW |
                            PixelFormatDescriptorFlagsEnum.PFD_SUPPORT_OPENGL |
                            PixelFormatDescriptorFlagsEnum.PFD_DOUBLEBUFFER);
        pfd.iPixelType = PIXELFORMATDESCRIPTOR.PFD_TYPE_RGBA;
        pfd.cColorBits = 24;
        pfd.cDepthBits = 16;
        pfd.iLayerType = PIXELFORMATDESCRIPTOR.PFD_MAIN_PLANE;

        var iFormat = GDI.ChoosePixelFormat(this.DC, ref pfd);
        GDI.SetPixelFormat(this.DC, iFormat, ref pfd);

        this.RC = wglCreateContext(this.DC);

        wglMakeCurrent(this.DC, this.RC);
}

我已将 User.GetForegroundWindow() 作为 hWnd 发送。

在此初始化之后,我尝试将屏幕截图放入图像中(并且我还尝试将其读入一个简单的字节数组)

glReadPixels 用法的简短伪代码:

var area = new Rectangle(0, 0, 100, 100);
var bmp = new Bitmap(area.Width, area.Height);
var data = bmp.LockBits(area, ILM.WriteOnly, PF.24bppRgb);

glReadBuffer(BACK);
glReadPixels(0, 0, area.Width, area.Height, BGR_EXT /*also tried RGB and RGBA*/, UNSIGNED_BYTE, data.Scan0);

bmp.UnlockBits(data);
bmp.Save(@"C:\Back.bmp");

data = bmp.LockBits(area, ILM.WriteOnly, PF.24bppRgb);

glReadBuffer(FRONT);
glReadPixels(0, 0, area.Width, area.Height, BGR_EXT /*also tried RGB and RGBA*/, UNSIGNED_BYTE, data.Scan0);

bmp.UnlockBits(data);
bmp.Save(@"C:\Front.bmp");

用一个简单而小的 byte[] 尝试它是这样完成的:

var bytes = new byte[10 * 10 * 3];
glReadPixels(0, 0, 10, 10, RGB, UNSIGNED_BYTE, bytes);

并且 byte[] 都是零。我也尝试过使用更大尺寸的数组(保持 0、0、10、10),但仍然无济于事。


在这两种情况下,结果是相同的。缓冲区根本没有改变,而 glGetError 调用在每次 GL 函数调用后返回 0。

Back.bmp 和 Front.bmp 都是全黑的。

请告诉我我做错了什么?谢谢

4

1 回答 1

3

您是要创建您渲染的内容的屏幕截图,还是一般屏幕的屏幕截图?

glReadPixels保证仅适用于 OpenGL 帧缓冲区的内容。它不适合拍摄其他任何东西的屏幕截图(曾经有一段时间,这是可能的,但自从合成窗口管理器出现以来,这些时代已经一去不复返了)。

因此,如果您尝试进行一般屏幕捕获,则glReadPixels是错误的方法。

但是,如果您尝试截取渲染内容的屏幕截图,则必须确保在调用glReadPixels时渲染的上下文也处于活动状态。

于 2011-09-21T08:49:02.800 回答