DirectX游戏LPD3DX9Sprite渲染缓慢

DirectX Game LPD3DX9Sprite Rendering Slow

本文关键字:缓慢 LPD3DX9Sprite 游戏 DirectX      更新时间:2023-10-16

嘿,我正在尝试在c++中构建一个可以使用DirectX和SDL同时处理数千个精灵的2D引擎。我听说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#中运行完美的许多精灵渲染。

可以说这就是罪魁祸首:

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,其中顶点和纹理在需要时流式传输到图形卡,而不是预加载它们并简单地调用命令来绘制预加载的顶点。你需要研究库是否有能力使用顶点缓冲对象和其他类似的结构提前将这些数据加载到图形卡上。

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

:

我听说LPD3DX9Sprite非常高效…

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

注意,ID3DXSprite::Draw方法不会将精灵绘制/渲染到屏幕上。它只是将精灵添加到批处理精灵列表中。有关ID3DXSprite接口中可用方法的信息,请参见此链接。你必须使用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->Flush();这段代码。然后Flush()方法将绘制所有的批处理精灵。