DirectX 游戏 LPD3DX9Sprite 渲染缓慢
DirectX Game LPD3DX9Sprite Rendering Slow
嘿,我正在尝试用 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。 Vsync 已启用,但无论如何都会发生减速。我能做些什么吗?
我觉得奇怪的是,这个没有真正逻辑的 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 中的编码风格,其中顶点和纹理在它们被传输到图形卡时需要,而不是预加载它们并简单地调用命令来绘制预加载的顶点。您需要研究库是否有能力使用顶点缓冲区对象和其他类似结构提前将此数据加载到显卡上。
如果没有,那么您需要自己学习和实施这些概念。
还有:
I heard that LPD3DX9Sprite is very efficient...
一般来说,根据定义,您使用 DirectX9 的任何情况都不会很快。除非您使用 DX10 和 DX11 的功能集,否则没有理由首先使用 DX9 功能。
注意,方法 ID3DXSprite::Draw
不会 draw/render 精灵到 screen.It 只是将精灵添加到可用方法的批处理 sprites.For 信息列表中在界面 ID3DXSprite
中看到这个 link。
您必须使用 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
loop.The Flush()
方法之后添加 Graphics::SpriteBatch->Flush();
这段代码,然后绘制所有批处理的精灵。
嘿,我正在尝试用 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。 Vsync 已启用,但无论如何都会发生减速。我能做些什么吗?
我觉得奇怪的是,这个没有真正逻辑的 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 中的编码风格,其中顶点和纹理在它们被传输到图形卡时需要,而不是预加载它们并简单地调用命令来绘制预加载的顶点。您需要研究库是否有能力使用顶点缓冲区对象和其他类似结构提前将此数据加载到显卡上。
如果没有,那么您需要自己学习和实施这些概念。
还有:
I heard that LPD3DX9Sprite is very efficient...
一般来说,根据定义,您使用 DirectX9 的任何情况都不会很快。除非您使用 DX10 和 DX11 的功能集,否则没有理由首先使用 DX9 功能。
注意,方法 ID3DXSprite::Draw
不会 draw/render 精灵到 screen.It 只是将精灵添加到可用方法的批处理 sprites.For 信息列表中在界面 ID3DXSprite
中看到这个 link。
您必须使用 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
loop.The Flush()
方法之后添加 Graphics::SpriteBatch->Flush();
这段代码,然后绘制所有批处理的精灵。