Just to add, you do not necessarily need an orthographic projection for 2d in DX11. You can do the transform yourself pretty easily on the CPU:
size_t Sprite::Draw(const Texture& d3dTexture, const math::Vector3& vPosition, const math::Vector3& /*vOrigin*/, const RECT& rSrcRect, const math::Vector2f& vScale, float /*fAngle*/)
{
RECT rSrc(rSrcRect);
const math::Vector2& vTextureSize(d3dTexture.GetSize());
const math::Vector2 vSrcSize(rSrcRect.right - rSrcRect.left, rSrcRect.bottom - rSrcRect.top);
const math::Vector2 vSize((int)(vSrcSize.x*vScale.x), (int)(vSrcSize.y*vScale.y));
// calculate the sprites vertices in screen space
// to speed up calculations, we multiply by 1.0 / screen size, which is calculated offline
float leftVertex = vPosition.x * m_vInvHalfScreenSize.x - 1.0f;
float rightVertex = leftVertex + vSize.x * m_vInvHalfScreenSize.x;
float topVertex = -vPosition.y * m_vInvHalfScreenSize.y + 1.0f;
float bottomVertex = topVertex - vSize.y * m_vInvHalfScreenSize.y;
const float leftCoord = rSrc.left / (float)vTextureSize.x;
const float rightCoord = rSrc.right / (float)vTextureSize.x;
const float topCoord = rSrc.top / (float)vTextureSize.y;
const float bottomCoord = rSrc.bottom / (float)vTextureSize.y;
SpriteVertex Vertices[] =
{
{ leftVertex, topVertex, vPosition.z, leftCoord, topCoord, 1.0f, 1.0f, 1.0f, 1.0f },
{ rightVertex, topVertex, vPosition.z, rightCoord, topCoord, 1.0f, 1.0f, 1.0f, 1.0f },
{ rightVertex, bottomVertex, vPosition.z, rightCoord, bottomCoord, 1.0f, 1.0f, 1.0f, 1.0f },
{ leftVertex, bottomVertex, vPosition.z, leftCoord, bottomCoord, 1.0f, 1.0f, 1.0f, 1.0f }
};
SpriteVertex* pBuffer = static_cast<SpriteVertex*>(m_mapped.pData);
memcpy(pBuffer + m_nextFreeId * 4, Vertices, sizeof(SpriteVertex)* 4);
return m_nextFreeId++;
}
This way, the vertices are already transformed, and you can simply pass them through in your vertex shader. This example works when you draw sprites with pixel coordinates, if you have them already in relative screen space (from 0.0f to 1.0f) the conversion is even simplier. Of course it depends whether this makes sense, but depending on your programs structure, it can make things easier if you don't have to have a orthogonal matric available for every shader that eigther draws a sprite or performs a fullscreen pass.