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!
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:
- Tnput layout describes the positions of the vertices in world space indicated as
SV_Position
. The input layout describes the format of the data.
For example:
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
Vertex shader input receives that information from the input assembler as decoded by the input layout from the vertex buffer, optionally using an index buffer as well. Whatever format the position is in, typically it's converted to
float
for use by the shader.The vertex shader has to produce the output vertex position, again indicated by
SV_Position
. This is the(x, y)
position of the pixel in normalized coordinates in the range(-1, -1)
to(1, 1)
. Thez
is the depth position (used for the depth buffer) in the normalized range0
to1
.
For example:
float4 VS( float4 Pos : SV_Position ) : SV_Position
{
return Pos;
}
The pixel shader can optionally take the position, but it doesn't have to. The
(x,y)
are in pixel coordinates. The vertex output ('clip space') is converted to pixels by using the viewport state that was provided inD3D11_VIEWPORT
.The pixel shader must produce a
float4
result marked asSV_Target
.
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 newSV_Position
(orSV_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.
来源:https://stackoverflow.com/questions/46527515/directx-11-pixel-shader-what-is-sv-position