directx-11hlslvertex-shaderpixel-shader

DirectX 11 Pixel Shader What Is SV_POSITION?


I am learning HLSL for DirectX 11, and I was wondering what exactly is the SV_POSITION that is the output for a Vertex Shader, and the input for a Pixel Shader.

1: Is this x,y,z of every pixel on your screen, or of the object?

2: Why is it 4 32bit floats?

3: Do you need this System Variable for the vertex output?

Thank you!


Solution

  • The vertex shader stage only has one required output: the position of the vertex. This value is then used by the fixed-function rasterizer to compute which pixels are being drawn and invoke the pixel shader for each one. That's what the system value semantic SV_Position indicates on the output of a vertex shader. A pixel shader doesn't actually need to take the pixel position as input, but it can if that is useful. The input layout must also have a position for the vertex shader which uses the SV_Position semantic as well.

    A typically set up is:

    For example:

    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    

    For example:

    float4 VS( float4 Pos : SV_Position ) : SV_Position
    {
        return Pos;
    }
    

    For example:

    // We can omit the position
    float4 PS() : SV_Target
    {
        return float4( 1.0f, 1.0f, 0.0f, 1.0f );
    }
    
    // Or you can take it as input if that's helpful
    float4 PS( float4 Pos : SV_Position ) : SV_Target
    {
        return float4( 1.0f, 1.0f, 0.0f, 1.0f );
    }
    

    Technically the vertex shader doesn't have to take a position as input. With Shader Model 4.0 or better hardware, you can use the SV_VertexId to self-generate the corners of a quad in a vertex shader with code like the following which doesn't make use of any input layout, vertex buffer, or index buffer at all. It still has to produce an output position for the pixel shader of course.

    VSInputTx VSQuad(uint vI : SV_VertexId)
    {
        VSInputTx vout;
    
        float2 texcoord = float2(vI & 1, vI >> 1);
        vout.TexCoord = texcoord;
    
        vout.Position = float4((texcoord.x - 0.5f) * 2, -(texcoord.y - 0.5f) * 2, 0, 1);
        return vout;
    }
    

    Note that you can use the older Direct3D 9 POSITION semantic in pretty much any place that you can use the new SV_Position (or SV_POSITION) semantic. The only requirement is that you have to be consistent between the input layout and the vertex shader input. Otherwise it will fail to bind.

    As you are new to DirectX, I recommend you take a look at the DirectX Tool Kit and in particular the built-in shader source.