HLSL PixelInputType semantics passing wrong values to pixel shader

Started by
3 comments, last by turanszkij 6 years, 2 months ago

I've been trying for hours now to find the cause of this problem. My vertex shader is passing the wrong values to the pixel shader, and I think it might be my input/output semantics.

*This shader takes in a prerendered texture with shadows in it, based on Rastertek Tutorial 42. So the light/dark values of the shadows are already encoded in the blurred shadow texture, sampled from Texture2D shaderTextures[7] at index 6 in the pixel shader.


struct VertexInputType
{
    float4 vertex_ModelSpace : POSITION;
    float2 tex : TEXCOORD0;
    float3 normal : NORMAL;
    float3 tangent : TANGENT;
    float3 binormal : BINORMAL;
};

struct PixelInputType
{
    float4 vertex_ModelSpace : SV_POSITION;
    float2 tex : TEXCOORD0;
    float3 normal : NORMAL;
    float3 tangent : TANGENT;
    float3 binormal : BINORMAL;
    float3 viewDirection : TEXCOORD1;
    float3 lightPos_LS[NUM_LIGHTS] : TEXCOORD2;
    float4 vertex_ScrnSpace : TEXCOORD5;
};

Specifically PixelInputType is causing a ton of trouble - if I switch the tags "SV_POSITION" for the first variable and "TEXCOORD5" for the last one, it gives completely different values to the Pixel shader even though all the calculations are exactly the same. Specifically, the main issues are that I have a spotlight effect in the pixel shader that takes the dot product of the light to Surface Vector with the light direction to give it a falloff, which was previously working, but in this upgraded version of the shader, it seems to be giving completely wrong values.
/

(See full vertex shader code below). Is there some weird thing about pixel shader semantics that Im missing? Does the order of the variables in the struct matter? I've also attached teh full shader files for reference. Any insight would be much appreciated, thanks.


PixelInputType main( VertexInputType input )
{
    //The final output for the vertex shader
    PixelInputType output;

    // Pass through tex coordinates untouched
    output.tex  = input.tex;

    // Pre-calculate vertex position in world space
    input.vertex_ModelSpace.w = 1.0f;

    // Calculate the position of the vertex against the world, view, and projection matrices.
    output.vertex_ModelSpace = mul(input.vertex_ModelSpace, cb_worldMatrix);
    output.vertex_ModelSpace = mul(output.vertex_ModelSpace, cb_viewMatrix);
    output.vertex_ModelSpace = mul(output.vertex_ModelSpace, cb_projectionMatrix);

    // Store the position of the vertice as viewed by the camera in a separate variable.
    output.vertex_ScrnSpace = output.vertex_ModelSpace;

    // Bring normal, tangent, and binormal into world space
    output.normal = normalize(mul(input.normal, (float3x3)cb_worldMatrix));
    output.tangent = normalize(mul(input.tangent, (float3x3)cb_worldMatrix));
    output.binormal = normalize(mul(input.binormal, (float3x3)cb_worldMatrix));

    // Store worldspace view direction for specular calculations
    float4 vertex_WS = mul(input.vertex_ModelSpace, cb_worldMatrix);
    output.viewDirection = normalize(cb_camPosition_WS.xyz - vertex_WS.xyz);

    for(int i = 0; i< NUM_LIGHTS; ++i)
    {
        // Calculate light position relative to the vertex in WORLD SPACE
        output.lightPos_LS[i] = cb_lights[i].lightPosition_WS - vertex_WS.xyz;
    }

    return output;
}


Repo link:

https://github.com/mister51213/DirectX11Engine/tree/master/DirectX11Engine

 

Light_SoftShadows_ps.hlsl

Light_SoftShadows_vs.hlsl

Advertisement

Semantics starting with SV_ are reserved "System Value" semantics which bring extended meaning and can behave differently than user semantics. Specifically in your case SV_Position will be modified by the rasterizer stage and will contain pixel coordinates in the XY components inside the pixel shader, while a TEXCOORD5 user semantic will contain the interpolated clip space coordinates as you have written them in the vertex shader.

The order of the input/output struct is important in the way that it must be the same in the different shader stages that write/read them.

3 minutes ago, turanszkij said:

Semantics starting with SV_ are reserved "System Value" semantics which bring extended meaning and can behave differently than user semantics. Specifically in your case SV_Position will be modified by the rasterizer stage and will contain pixel coordinates in the XY components inside the pixel shader, while a TEXCOORD5 user semantic will contain the interpolated clip space coordinates as you have written them in the vertex shader.

The order of the input/output struct is important in the way that it must be the same in the different shader stages that write/read them.

So the var with the SV_POSITION tag gets OVERWRITTEN by the Gpu but any other tagged variable will be whatever I assign it, is that correct? And other than the PixelInput struct declaration being exactly the same in vertex and pixel shaders, there is no requirement for the members of the struct to be in a particular order, right? Also, do these user tags like TEXCOORD5 need to be defined anywhere else as do the vertexinput semantics in the shader class? Or can they just be named whatever I want? Thank you so much.

You can name the shader semantics however you want (except for the System-Value ones). The order of the semantics should match between the stages, but a following stage can also be just a subset of the input structure. For example sometimes there is no need for a pixel shader to read the whole contents of a vertex shader output structure, so the declaration of the struct can just be a subset of that in the PS, but with the same order and data layout. And lastly, there is nowhere else that you should declare shader structure names except in the shaders themselves, except only for the input layout as you mentioned.

This topic is closed to new replies.

Advertisement