【发布时间】:2013-10-11 23:28:00
【问题描述】:
我正在玩一些 Delphi + openGL。因为懒,想用FireMonkey给我做个表格。
所以我做了一个 FireMonkeyHD 应用程序,初始化了 GL,渲染了一个基本的立方体......并发现了一些奇怪的行为。当我不移动鼠标时,我得到大约 10FPS。当我移动鼠标时,性能轻松提升到 500FPS 甚至(显然)更高。那可能是什么?
*注意:我在主线程中使用 onKeyDown 事件开始渲染...
为了更好地理解,两张图:
一些代码:
unit Unit1;
interface
uses
{ ... }
;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
Shift: TShiftState);
private
degen
: IDeGEn;
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
var
DeGEnFactory
: TDeGEnFactory;
begin
{ ... }
// Load DeGEn
degen := DeGEnFactory.newDeGEn(WindowHandleToPlatform(Form1.Handle).Wnd);
// Initialize
degen.get3D.init(600, 800);
degen.get3D.setOnRender(function : Boolean
var
v3d
: R3DVector;
begin
Result := true;
self.Caption := IntToStr(degen.get3D.getFPS);
v3d.z := 0.01;
degen.get3D.getCamera.move(v3d);
degen.get3D.renderTest;
end);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
// Shut down DeGEn
{ ... }
end;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
Shift: TShiftState);
begin
// Start rendering
degen.startRendering;
end;
end.
startRendering 看起来像这样:
procedure TDeGEn.startRendering;
var
msg
: TMsg;
begin
if isRendering then
begin
Exit;
end;
isRendering := true;
while GetMessage(msg, 0, 0, 0) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
if not degen3D.render then
begin
Break;
end;
end;
isRendering := false;
end;
您可能很容易注意到,相机只是以取决于 FPS 的速度远离立方体。我还将 FPS 显示为表单标题。
【问题讨论】:
-
这是非常老的 Windows 应用程序中的常见行为。除非屏幕被标记为“脏”,否则他们不会重绘屏幕。将鼠标移到屏幕的一部分上是一种将控件标记为脏并强制重新绘制的可靠方法。这可能不是您的情况的罪魁祸首,但我怀疑它与您的消息泵有某种联系,并且移动光标会增加您的消息泵中发生绘图所需的某些事情的频率。
-
说到魔鬼,我相信这是你的罪魁祸首:
while GetMessage(msg, 0, 0, 0) do。如果您没有待处理的窗口消息,则完全跳过循环。已经有一段时间了,Pascal 有 Do While 吗? :) 无论是否有等待消息,您都希望至少调用一次此循环以让degen3D.render做某事。 -
好吧,我能看到的唯一渲染代码部分是在您的消息泵中。如果没有待处理的消息,您的消息泵循环将提前退出。
-
@Andon 你搞错了。当队列为空时,GetMessage 会阻塞。
-
@Marco 为什么要添加消息循环?您的应用已经有一个。为什么需要第二个?
标签: delphi opengl firemonkey onkeydown