Shader texcoord misuse (ps_2_0/XNA > ps_4_0/MonoGame)

Hello there,

I am fairly new to shaders, but I had one working in my XNA project.
It basically replaces certain colors with other colors in the Pixel Shader.

sampler2D input : register(s0);

float4 FromColor1 : register(C0);
float4 FromColor2 : register(C1);
float4 FromColor3 : register(C2);
float4 FromColor4 : register(C3);

float4 ToColor1 : register(C4);
float4 ToColor2 : register(C5);
float4 ToColor3 : register(C6);
float4 ToColor4 : register(C7);

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 Color = tex2D(input, uv);

    if (Color.r == FromColor1.r && Color.g == FromColor1.g && Color.b == FromColor1.b)
        return ToColor1;
    if (Color.r == FromColor2.r && Color.g == FromColor2.g && Color.b == FromColor2.b)
        return ToColor2;
    if (Color.r == FromColor3.r && Color.g == FromColor3.g && Color.b == FromColor3.b)
        return ToColor3;
    if (Color.r == FromColor4.r && Color.g == FromColor4.g && Color.b == FromColor4.b)
        return ToColor4;

    return Color;
}

technique Technique1
{
    pass Pass1
    {
        PixelShader = compile ps_4_0 main();
    }
}

This is what the code looks like in MonoGame now, which is the exact same as in XNA, but with a tiny change: the ps compile statement changed from ps_2_0 to ps_4_0.

This seems to cause the following problem:
Instead of using the texture coordinate uv correctly, it just always takes the pixel at 0, 0. I have tried using a Vertex Shader to input the position data, but that gave me the same result.

Does anyone know if that is a problem due to the 4.0 Pixel Shader compiler, or if that is a bug, and how to possibly fix this?

Now, uv would not be correct with only uv in the input. Depending on the vertex declaration and vertex shader you use – if you are using the SpriteBatch the VS input would be SV_Position, Color, Texcoord… so try this instead:

float4 main(float4 position : SV_Position, float4 col : COLOR0, float2 uv : TEXCOORD0) : COLOR0

Even though you may not use position or col - I think this is so they are set in the correct registers.

3 Likes

Sorry for replying this late, but it works, thank you very much :smiley:

Yeah, it was the SpriteBatch definition, forgot to include that somehow :confused:

Just out of curiosity, is the restriction to keep all parameters in related to the ps_4_0 or MonoGame?

Oh good - glad to hear it works now. :smile:
I do know that xna was dx9 and MonoGame (depending on platform) will use something like DirectX11+ for example which no longer provides a fixed function pipeline and thus needs a specified vertex shader. The spritebatch has its own vertex shader (which you can over-ride with your own effect) which is able to color sprites so it takes those variables in that order as input and also as output which the pixel shader needs to receive in a matching way.
I know from programming DX11 and sharpDX that the hlsl stuff needs to be set up this way. I believe the same may be true of newer OpenGL and glsl – although I’m not entirely sure. I know it does work in a very similar manner.

You saved my life - this information was surprisingly difficult to find and I was trying to convert some DX9 shaders.