DirectX 游戏 LPD3DX9Sprite 渲染缓慢

Posted

技术标签:

【中文标题】DirectX 游戏 LPD3DX9Sprite 渲染缓慢【英文标题】:DirectX Game LPD3DX9Sprite Rendering Slow 【发布时间】:2015-10-27 16:17:32 【问题描述】:

嘿,我正在尝试用 C++ 构建一个 2D 引擎,它可以同时使用 DirectX 和 SDL 处理数千个精灵。我听说 LPD3DX9Sprite 非常高效,来自 XNA 的风格对我来说非常熟悉。我正在做一些性能测试,一次批处理多个精灵(相同的纹理和设置)。但是,性能和原因似乎存在一些问题。

void Draw()


Graphics::direct3D_device->Clear(1, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(255, 0, 0, 0), 0, 0);
Graphics::direct3D_device->BeginScene();

Graphics::SpriteBatch->Begin(D3DXSPRITE_ALPHABLEND);

string fs = std::to_string(fps);


for (int i = 0; i < 1000; i++)
    Test.Draw();

DrawTextString(32, 64, fs.c_str());

Graphics::SpriteBatch->End();

Graphics::direct3D_device->EndScene();
Graphics::direct3D_device->Present(NULL, NULL, NULL, NULL);

这是我的绘制代码,它调用了一个基本上调用 LPD3DX9Sprite 对象的 DrawMethod 的函数。游戏中并没有真正发生其他事情,只是这个绘图代码。

根据 fps 计数器,我得到 4fps。垂直同步已启用,但无论如何都会出现减速。对此我能做些什么吗?

我觉得奇怪的是,与一个完整的 C# 游戏引擎相比,这个没有真正逻辑的简单 C++ 测试游戏是在爬行。

【问题讨论】:

Test.draw();的内容是什么? Graphics::SpriteBatch->Draw(Texture, &SourceRect, &OriginPos, &D3DXVECTOR3(Position.x,Position.y,0), Color);我什至还没有为旋转和缩放添加任何变换。就是这个。 【参考方案1】:

可以说这是罪魁祸首:

for (int i = 0; i < 1000; i++)
    Test.Draw();

连同您声称的Test.draw(); 的内容:

Graphics::SpriteBatch->Draw(Texture, &SourceRect, &OriginPos, &D3DXVECTOR3(Position.x,Position.y,0), Color);

尽管这是一个相对简单的命令,但必须一遍又一遍地推送到显卡是一个相当昂贵的命令。我不知道你正在使用的库的底层机制,但是当这样编写命令时,它强烈地唤起了 OpenGL1.x 中的编码风格,其中顶点和纹理按原样流式传输到显卡需要,而不是预加载它们并简单地调用命令来绘制预加载的顶点。您需要研究该库是否有能力使用 Vertex Buffer Objects 和其他类似结构提前将这些数据加载到显卡上。

如果没有,那么您需要自己学习和实施这些概念。

还有:

听说LPD3DX9Sprite效率很高……

一般来说,根据定义,任何使用 DirectX9 的情况都不会很快。除非您使用 DX10 和 DX11 的功能集,但在这种情况下,没有理由首先使用 DX9 功能。

【讨论】:

谢谢,我会寻找更好的方法。我想真的没有一个简单的出路。 SpriteBatch 在 Direct3D 11 中使用 DirectX Tool Kit 是最简单的方法。【参考方案2】:

注意,ID3DXSprite::Draw 方法不会将精灵绘制/渲染到屏幕上。它只是将精灵添加到批处理精灵列表中。有关接口ID3DXSprite 中可用方法的信息,请参阅@987654321 @。 您必须使用HRESULT Flush() 来绘制所有批处理的精灵。

所以你的代码应该这样修改,

void Draw()


 Graphics::direct3D_device->Clear(1, NULL, D3DCLEAR_TARGET,D3DCOLOR_ARGB(255, 0, 0, 0), 0, 0);
 Graphics::direct3D_device->BeginScene();

 Graphics::SpriteBatch->Begin(D3DXSPRITE_ALPHABLEND);

 string fs = std::to_string(fps);


 for (int i = 0; i < 1000; i++)
 
   Test.Draw();
 
 Graphics::SpriteBatch->Flush();//Basically call the Flush Method here
 DrawTextString(32, 64, fs.c_str());

 Graphics::SpriteBatch->End();

 Graphics::direct3D_device->EndScene();
 Graphics::direct3D_device->Present(NULL, NULL, NULL, NULL);

基本上,您需要在for 循环之后添加Graphics::SpriteBatch-&gt;Flush(); 这段代码。然后Flush() 方法将绘制所有批处理的精灵。

【讨论】:

我查看了描述,似乎 Flush();无论 End() 何时调用方法;方法被调用。我也尝试了您的建议,但游戏仍然运行缓慢。

以上是关于DirectX 游戏 LPD3DX9Sprite 渲染缓慢的主要内容,如果未能解决你的问题,请参考以下文章

挂钩/覆盖 DirectX 游戏?

DirectX 游戏挂钩

巫师3directx11是啥

开始 DirectX 11 游戏编程错误

使用 Direct 3D (C++) 的 DIrectX 11 2D 游戏引擎

如何通过命令提示符运行 DirectX 游戏