将 OpenGL 场景保存到 TBitmap - glReadPixels 返回空数据?

发布于 2024-11-07 11:29:31 字数 958 浏览 0 评论 0原文

我正在尝试将 OpenGL 创建的场景保存为 TBitmap。我遇到的问题是 glReadPixels 返回所有空数据(全 0)。思考为什么会发生这种情况?我正在尝试捕获当前的 OpenGL 上下文。 (屏幕上的显示一切正常)。这是 Windows 下的 Delphi 7。

var
   pbuf: pointer;
   y: integer;
   bmp: TBitmap;
   p1, p2: pointer;
begin
   GetMem( pbuf, pnScene.Width * pnScene.Height * 4);
   glReadPixels( 0, 0, pnScene.Width, pnScene.Height, GL_RGBA, GL_UNSIGNED_BYTE, pbuf);
   //<------  pbuf now contains all 0's  ---------->

   bmp := TBitmap.Create;
   bmp.PixelFormat := pf32bit;
   bmp.Width := pnScene.Width;
   bmp.Height := pnScene.height;

   for y := 0 to (pnScene.Height -1) do
   begin
      p1 := bmp.ScanLine[y];
      p2 := pointer( integer(pbuf)+ (y * bmp.Width * 4));
      CopyMemory( p1, p2, bmp.Width * 4);
   end;

   bmp.SaveToFile( 'c:\test\temp.bmp');
   bmp.Free;
   FreeMem( pbuf);
end;

非常欢迎提出建议/想法!

附录:

最终计划是在渲染调用之后立即调用 glReadPixels() 来录制视频。当我这样做时,效果很好,所以这最终不是问题。

I'm attempting to save an OpenGL created scene as a TBitmap. The problem I'm having is glReadPixels is returning all empty data (all 0's). Thoughts on why this would occur? I'm attempting to capture the currentl OpenGL context. (display on screen is all working fine). This is with Delphi 7 under Windows.

var
   pbuf: pointer;
   y: integer;
   bmp: TBitmap;
   p1, p2: pointer;
begin
   GetMem( pbuf, pnScene.Width * pnScene.Height * 4);
   glReadPixels( 0, 0, pnScene.Width, pnScene.Height, GL_RGBA, GL_UNSIGNED_BYTE, pbuf);
   //<------  pbuf now contains all 0's  ---------->

   bmp := TBitmap.Create;
   bmp.PixelFormat := pf32bit;
   bmp.Width := pnScene.Width;
   bmp.Height := pnScene.height;

   for y := 0 to (pnScene.Height -1) do
   begin
      p1 := bmp.ScanLine[y];
      p2 := pointer( integer(pbuf)+ (y * bmp.Width * 4));
      CopyMemory( p1, p2, bmp.Width * 4);
   end;

   bmp.SaveToFile( 'c:\test\temp.bmp');
   bmp.Free;
   FreeMem( pbuf);
end;

And suggestions/thoughts are greatly welcome!

Addendum:

Ultimately the plan was to place the glReadPixels() call right after the rendering calls for purposes of recording video. When I did that, it worked ok, so this ended up being something of a non-problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

痴情 2024-11-14 11:29:31

确保您在创建 GL 上下文的同一线程中执行此操作。如果这是您提供给第三方库的回调函数,那么它可能会在另一个线程中执行,而您甚至没有意识到。这发生在我身上一次,我得到的只是零,就像你一样。

Make sure you are doing this from the same thread as where you created the GL context. If this is a callback function you supply to a third-party library then it may execute in another thread without you even realizing it. This happened to me once and all I got was zeroes just like you.

原野 2024-11-14 11:29:31

我假设您想要检索已交换到双缓冲窗口的前缓冲区的图片。然后尝试在 glReadPixels(...) 之前添加 glReadBuffer(GL_FRONT)

I assume you want to retrieve a picture that has been already swapped to the front buffer of a double buffered window. Then try prepending a glReadBuffer(GL_FRONT) before glReadPixels(...)

妳是的陽光 2024-11-14 11:29:31

for 循环中,您必须将语句更改为:

p1 := bmp.ScanLine[y];

to

p1 := bmp.ScanLine[OpenGlPanel.Height -1 -y];

否则,复制的位图将是颠倒的。

In the for loop you must change the statement:

p1 := bmp.ScanLine[y];

to

p1 := bmp.ScanLine[OpenGlPanel.Height -1 -y];

Otherwise, the copied bitmap will be upside-down.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文