【发布时间】:2021-10-14 11:51:15
【问题描述】:
如果您正在尝试对游戏进行编程,您真的不应该等待来自操作系统的WM_PAINT 信号来绘制。您应该尽快重复绘制。
为什么在 D3D 示例代码中是rendering happening in WM_PAINT?
如何在不等待来自操作系统的WM_PAINT 信号的情况下重新处理 D3D12 示例以尽快渲染?
【问题讨论】:
标签: direct3d12
如果您正在尝试对游戏进行编程,您真的不应该等待来自操作系统的WM_PAINT 信号来绘制。您应该尽快重复绘制。
为什么在 D3D 示例代码中是rendering happening in WM_PAINT?
如何在不等待来自操作系统的WM_PAINT 信号的情况下重新处理 D3D12 示例以尽快渲染?
【问题讨论】:
标签: direct3d12
GitHub: DirectX-Graphics-Samples 上的“Hello, World”DirectX 12 示例依赖于这样一个事实:如果您调用 PeekMessage 并且没有其他可用消息,它创建一条 WM_PAINT 消息:
MSG msg = {};
while (msg.message != WM_QUIT)
{
// Process any messages in the queue.
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
通常游戏渲染循环不依赖于“神奇的 WM_PAINT”行为,而我在 GitHub: directx-vs-templates 中所拥有的:
MSG msg = {};
while (WM_QUIT != msg.message)
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
g_game->Tick();
}
}
g_game.reset();
WM_PAINT 唯一要做的就是清除屏幕——对调整大小进行特殊处理:
case WM_PAINT:
if (s_in_sizemove && game)
{
game->Tick();
}
else
{
PAINTSTRUCT ps;
(void)BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
break;
这里
Tick是一个执行Update和Render的方法,但根据StepTimer的模式,它可能每帧调用Update不止一次。
最终,两个 Win32 的“消息泵”实现了基本相同的目标。
【讨论】:
BeginPaint/EndPaint 以向Win O/S 发出您已绘制窗口的信号。我认为正在发生的事情是WM_PAINT 消息被一遍又一遍地重新发送,因为客户区没有得到验证,因为对BeginPaint/EndPaint 的调用丢失了