0

I know this had been asked a million times, but I just don't get some details.

As an example, lets say that I have a swap chain created and one staging ID3D11Texture2D.

What I can do with it is load a bitmap into this 2D texture and then copy it to the render target (assuming the size and format of both resources are the same).

Now I would like to display a sprite over that. One solution is to use vertex and pixel shaders. My understanding problem starts here.

Vertex shader:
I guess I should draw 2 triangles (2 triangles makes a rectangle, or a quad). DirectX is using left handed coordinate system, but I guess it's irrelevant here, because I'm dealing with 2D sprites, right? For the same reason, I assume I can ignore the world->view->projection transformations, right? Actually, I only need translation here in order to place the sprite at the right place on the screen, right?

Should the coordinates of these two triangles match the sprite dimensions, plus translation? In what order should I provide these vertices? Should the origin of the coordinate system be in the center of the sprite, or should the origin be at the top left corner of the sprite?

As an example, if I have 80x70 sprite, what would be the vertex values?

The real vertices: (X, Y, Z - with no translation applied)

1. -40, -35, 0
2. -40,  35, 0
3.  40, -35, 0
4.  40,  35, 0
5. -40,  35, 0
6.  40, -35, 0

Is that correct?

The rasterization step should call pixel shader once for each pixel in the sprite. The output of the vertex shader will be input for the pixel shader. Does that mean the pixel shader should have access to the sprite in order to return the correct pixel value when called?

some_user
  • 11
  • 2
  • Copying to the render target is not particularly fast. You can draw a textured 'full-screen quad', which is actually faster as a 'big triangle' which gets clipped by the hardware. See [FullScreenQuad](https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/FullScreenQuad) – Chuck Walbourn Oct 16 '19 at 04:07
  • Can you define "not particularly fast"? The `FullScreenQuad` is using DirectX 12. I'm not familiar with it and it's quite complex. – some_user Oct 16 '19 at 12:34
  • Look further down the file... it uses DX12 or DX11. – Chuck Walbourn Oct 16 '19 at 16:42

1 Answers1

0

For 2D drawing, you generally use a world->view->projection that converts classic 'pixel space' to the clip space (-1..1).

float xScale = 2.0f / ViewPortWidth;
float yScale = 2.0f / ViewPortHeight;

[ xScale, 0        0, 0, ]
[ 0,      -yScale, 0, 0, ]
[ 0,      0,       1, 0, ]
[ -1,     1,       0, 1  ]

The -1 and -yScale values are negated so that 0,0 is at the upper-left.

The Vertex Shader would do the transform to clip space:

void SpriteVertexShader(inout float4 color    : COLOR0,
                        inout float2 texCoord : TEXCOORD0,
                        inout float4 position : SV_Position)
{
    position = mul(position, MatrixTransform);
}

The points of the quad are then rasterized, then the Pixel Shader is invoked:

Texture2D<float4> Texture : register(t0);
sampler TextureSampler : register(s0);

float4 SpritePixelShader(float4 color    : COLOR0,
                         float2 texCoord : TEXCOORD0) : SV_Target0
{
    return Texture.Sample(TextureSampler, texCoord) * color;
}

See SpriteBatch in the DirectX Tool Kit.

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81
  • I did take a look at the DirectX Tool Kit, but it's too complex for learning. I need discreet chunks with explanations. Your answer gave me enough information for further digging. Thanks. – some_user Oct 16 '19 at 12:37
  • Just one detail, please... The last row in the matrix above, starts with -1, 1. That maps pixel space to the clip space [-1, 1]? – some_user Oct 16 '19 at 14:29
  • That shifts the viewport range up and to the left. Remember that clip space is -1,-1 to 1,1 with 0,0 being in the *middle* of the viewport. – Chuck Walbourn Oct 16 '19 at 16:43