views:

75

answers:

1

I am currently trying to get used to the DirectX API and I am wondering what is the usual approach to render a sprite in DirectX 11 (e.g. for a tetris clone).

Is there a simmilar interface as ID3DX10Sprite, and if not, which would be the usual method to draw sprites in DirectX 11?

Edit: Here is the HLSL code that worked for me (the computation of the projection coordinate could be done better):

struct SpriteData
{
    float2 position;
    float2 size;
    float4 color;
};

struct VSOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

cbuffer ScreenSize : register(b0)
{
    float2 screenSize;
    float2 padding; // cbuffer must have at least 16 bytes
}

StructuredBuffer<SpriteData> spriteData : register(t0);

float2 GetVertexPosition(uint VID)
{
    [branch] switch(VID)
    {
        case 0:
            return float2(0, 0); 
        case 1:
            return float2(1, 0); 
        case 2:
            return float2(0, 1); 
        default:
            return float2(1, 1);
    }
}

float4 ComputePosition(float2 positionInScreenSpace, float2 size, float2 vertexPosition)
{
    float2 origin = float2(-1, 1);
    float2 vertexPositionInScreenSpace = positionInScreenSpace + (size * vertexPosition);

    return float4(origin.x + (vertexPositionInScreenSpace.x / (screenSize.x / 2)), origin.y - (vertexPositionInScreenSpace.y / (screenSize.y / 2)), 1, 1);
}

VSOut VShader(uint VID : SV_VertexID, uint SIID : SV_InstanceID)
{
    VSOut output;

    output.color = spriteData[SIID].color;
    output.position = ComputePosition(spriteData[SIID].position, spriteData[SIID].size, GetVertexPosition(VID));

    return output;
}

float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}
+2  A: 

No there isn't an equivalent. Usual method would be to draw a triangle strip forming a quad.

You could make use of instancing, so you just have to update a buffer with sprite data (x, y screen position in pixels, id of the texture to fetch in a texture array, scaling, rotation, layer, etc) and use shaders for rendering all sprites in one single draw call.

Here's some HLSL tidbits off the top of my head:

//--------------------------------------------------------------------------------------
// Shader code for Sprite Rendering
//--------------------------------------------------------------------------------------

struct Sprite {
    float2 position; // x, y world position
    float rotation;
    float scaling;

    float layer; // if you have multiple layers of sprites (e.g. background sprites)
    uint textureId;
};

StructuredBuffer<Sprite> SpritesRO : register( t0 );
Texture2DArray<float4> TextureSlices : register (t1);

cbuffer cbRenderConstants : register( b0 )
{
    matrix g_mViewProjection;
    // other constants
};

struct VSSpriteOut
{
    float3 position : SV_Position;
    uint textureId;
};

//-------------------------------------------------------------------------------------            
// Sprite Vertex Shader
//-------------------------------------------------------------------------------------

VSSpriteOut SpriteVS(uint VID : SV_VertexID, uint SIID : SV_InstanceID)
{
    VSSpriteOut Out = (VSSpriteOut)0;

    // VID is either 0, 1, 2 or 3
    // We can map 0 to position (0,0), 1 to (0,1), 2 to (1,0), 3 to (1,1)

    // We fetch the sprite instance data accord SIID
    Sprite sdata = SpritesRO[SIID];

    // function f computes screen space vertex position
    float3 pos = f (g_mViewProjection, VID, position, rotation, scaling, layer etc)

    Out.position = pos;
    Out.textureId = sdata.textureId;

    return Out;
}

//-------------------------------------------------------------------------------------
// Sprite Pixel Shader
//-------------------------------------------------------------------------------------

float4 SpritePS(VSSpriteOut In) : SV_Target
{
    // use In.textureId to fetch the right texture slice in texture array
    return color;
}
Stringer Bell
@Stringer Bell: Could you give me a short code example please? I struggle to get started with the buffer.
mpistrich
Check out all D3D11 samples from DXSDK, and look carefully how they do for creating Buffers, binding them, updating them, etc.
Stringer Bell
Wow, thank you. This really helped me getting started :)
mpistrich