我的应用程序需要绘制许多精灵。但这似乎有点慢(30架正在互相战斗的飞机,意味着+ 30枚动画火箭和爆炸)。
如何解决此问题,使其动画流畅?预先感谢您的帮助!
不知道如何解决这个问题。
struct d3dsprite_s {
std::wstring wszFile; //File name
LPD3DXSPRITE pSprite; //Pointer to the sprite object
LPDIRECT3DTEXTURE9 pTexture; //Pointer to the sprite texture
int iFrameCount; //Total amount of frames
int iFramesPerLine; //Amount of frames per line
int iFrameWidth; //Single frame width
int iFrameHeight; //Single frame height
};
std::vector<d3dsprite_s> m_vSprites;
HD3DSPRITE LoadSprite(const std::wstring& wszTexture, int iFrameCount, int iFrameWidth, int iFrameHeight, int iFramesPerLine, const bool bForceCustomSize = false)
{
//Load sprite
if (!wszTexture.length())
return GFX_INVALID_SPRITE_ID;
d3dsprite_s sSpriteData;
//Create sprite
if (FAILED(D3DXCreateSprite(this->m_pDevice, &sSpriteData.pSprite)))
return GFX_INVALID_SPRITE_ID;
//Load texture from file
if (FAILED(D3DXCreateTextureFromFileEx(this->m_pDevice, wszTexture.c_str(), (bForceCustomSize) ? iFrameWidth : D3DX_DEFAULT_NONPOW2, (bForceCustomSize) ? iFrameHeight : D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0xFF000000, nullptr, nullptr, &sSpriteData.pTexture))) {
sSpriteData.pSprite->Release();
return GFX_INVALID_SPRITE_ID;
}
//Save further data
sSpriteData.wszFile = wszTexture;
sSpriteData.iFrameCount = iFrameCount;
sSpriteData.iFramesPerLine = iFramesPerLine;
sSpriteData.iFrameWidth = iFrameWidth;
sSpriteData.iFrameHeight = iFrameHeight;
//Add to list
this->m_vSprites.push_back(sSpriteData);
//Return handle
return sSpriteData.pSprite;
}
bool DrawSprite(const HD3DSPRITE hSprite, int x, int y, int iFrame, float fRotation, int rotx, int roty, float fScale1, float fScale2, const bool bUseCustomColorMask, byte r, byte g, byte b, byte a)
{
//Add sprite to drawing list
if (!hSprite)
return false;
//Find sprite
size_t uiSprite = this->FindSprite(hSprite);
if (uiSprite == GFX_INVALID_LIST_ID)
return false;
if ((!this->m_vSprites[uiSprite].pTexture) || (!this->m_vSprites[uiSprite].pSprite))
return false;
//Calculate horizontal line ID
int iFrameLineId = (this->m_vSprites[uiSprite].iFramesPerLine > 0) ? iFrame / this->m_vSprites[uiSprite].iFramesPerLine : 0;
//Calculate vertical frame ID
int iFrameVerticalId = (this->m_vSprites[uiSprite].iFramesPerLine > 0) ? iFrame % this->m_vSprites[uiSprite].iFramesPerLine : 0;
//Calculate x position of frame
int iFrameXPos = iFrameVerticalId * this->m_vSprites[uiSprite].iFrameWidth;
//Calculate y position of frame
int iFrameYPos = iFrameLineId * this->m_vSprites[uiSprite].iFrameHeight;
//Setup rectangle info
RECT sRect;
sRect.top = iFrameYPos;
sRect.left = iFrameXPos;
sRect.bottom = iFrameYPos + this->m_vSprites[uiSprite].iFrameHeight;
sRect.right = iFrameXPos + this->m_vSprites[uiSprite].iFrameWidth;
//Begin drawing sprite
if (FAILED(this->m_vSprites[uiSprite].pSprite->Begin(D3DXSPRITE_ALPHABLEND)))
return false;
//Setup vector with position
D3DXVECTOR2 vPosition = { (float)x, (float)y };
//Setup vector with sprite center
D3DXVECTOR2 vRotCenter;
if ((rotx != -1) && (roty != -1))
vRotCenter = { (float)(rotx), (float)(roty) };
else
vRotCenter = { (float)(this->m_vSprites[uiSprite].iFrameWidth / 2) , (float)(this->m_vSprites[uiSprite].iFrameHeight / 2) };
D3DXMATRIX vNewMatrix;
//Setup scale vector
D3DXVECTOR2 vScale(fScale1, fScale2);
//Calculate transformation matrix
if (!D3DXMatrixTransformation2D(&vNewMatrix, ((fScale1 != 0.0f) && (fScale2 != 0.0f)) ? &vRotCenter : nullptr, 0.0f, ((fScale1 != 0.0f) && (fScale2 != 0.0f)) ? &vScale : nullptr, (D3DXVECTOR2*)&vRotCenter, fRotation, &vPosition))
return false;
//Apply transformation
if (FAILED(this->m_vSprites[uiSprite].pSprite->SetTransform(&vNewMatrix)))
return false;
//Add sprite to batch list
if (FAILED(this->m_vSprites[uiSprite].pSprite->Draw(this->m_vSprites[uiSprite].pTexture, &sRect, nullptr, nullptr, (bUseCustomColorMask) ? D3DCOLOR_RGBA(r, g, b, a) : 0xFFFFFFFF)))
return false;
//End drawing sprite
return SUCCEEDED(this->m_vSprites[uiSprite].pSprite->End());
}
const size_t FindSprite(const HD3DSPRITE hSprite)
{
//Get list ID of sprite handle if exists
for (size_t i = 0; i < this->m_vSprites.size(); i++) {
if (this->m_vSprites[i].pSprite == hSprite)
return i;
}
return GFX_INVALID_LIST_ID;
}
预期:快速绘制精灵 实际:子画面绘制缓慢
答案 0 :(得分:0)
主要问题是,至少根据上面的代码,您为每个精灵使用了不同的ID3DX11Sprite
实例。这消除了Sprite机制批量渲染的机会,因此您浪费了最大的渲染时间。它必须捕获状态,更新VB / IB,设置VB / IB和所有渲染状态,绘制4个点,然后在每个精灵上恢复状态。那样会很慢。
您应该为所有绘图使用ID3DX11Sprite
的一个实例,并在调用Begin
的 one 之间绘制尽可能多的精灵。并打给End
。
Direct3D 9是旧版。
ID3DX11Sprite
是已弃用的D3DX9
的一部分,仅在寿命终止的DirectX SDK中可用。参见Microsoft Docs。对于任何现代应用程序,使用Direct3D 11或Direct3D 12都会更好。 DirectX Tool Kit中的
SpriteBatch
提供了有效绘制精灵所需的功能,以及纹理加载器等。请参见Living without D3DX。