Two textures in a shader ?

So i suck with shaders in monogame i really haven’t messed with them too much.
Im trying to get two textures to run in a simple shader.
However the second texture sampler is filled with zeros it seems when i try to read its alpha.
I have no clue why?
Further im not really all to sure what the registers do here especially with multiple textures.
I was never that good to begin with at shader semmantics in xna or hlsl, in monogame im even more confused. Any help or explinations are appreciated feel free to get as short or long winded as you wish.

//_______________________________
// basic shader
#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1
#endif

Texture2D TextureA : register(t0);
sampler TextureSamplerA : register(s0)
{
    Texture = (TextureA);
};

Texture2D TextureB : register(t0);
sampler TextureSamplerB : register(s1)
{
    Texture = (TextureB);
};

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float4 Color : COLOR0;
    float2 TexureCoordinate : TEXCOORD0;
};
struct VertexShaderOutput
{
    float4 Position : SV_Position;
    float4 Color : COLOR0;
    float2 TexureCoordinate : TEXCOORD0;
};
struct PixelShaderOutput
{
    float4 Color : COLOR0;
};

VertexShaderOutput VertexShaderFunctionB(VertexShaderInput input)
{
    VertexShaderOutput output;
    output.Position = input.Position;
    output.Color = input.Color;
    output.TexureCoordinate = input.TexureCoordinate;
    return output;
}

// arrgg humm 
PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
    PixelShaderOutput output;
    // test
    float4 ca = tex2D(TextureSamplerA, input.TexureCoordinate) * input.Color;
    // cb is filled with zeros ?
    float4 cb = tex2D(TextureSamplerB, input.TexureCoordinate) * input.Color;
    if (cb.a > 1) ca.rgba = 250;
    output.Color = ca;
    //
    return output;
}
technique BlankTechniqueB
{
    pass
    {
        VertexShader = compile VS_SHADERMODEL VertexShaderFunctionB();
        PixelShader = compile PS_SHADERMODEL PixelShaderFunction();
    }
}

It seems, you are using the same register for both textures? That said, I don’t use any declaration of registers in any of my shaders. It might be helpful, when setting up the sampler from the C# side. Then you need to know where your texture is, meaning which register it is in. I think the SpriteBatch is always using the same register for its texture…

If i set the s1 register to 0 it fails to compile if i set the texture register t to 0 or 1 i get nothing. This is being used for DrawIndexPrimitves.

Honestly if i knew how to rip the register calls out at the moment i would. There are so few examples of how to do this and google doesn’t help much. I’ve been at this for hours already.

It would also be good to understand how i need to set these registers up between the code in hlsl and in game1.

I don’t use indicies for my declarations either, I just plainly assign them such as:

HLSL:

Texture2D TextureA;
sampler2D TextureASampler  = sampler_state 
{ 
	Texture = <TextureA>; 
};

Texture2D TextureB;
sampler2D TextureBSampler = sampler_state 
{ 
	Texture = <TextureB>; 
};

C#:

private void SetParameters(Texture2D textureA, Texture2D textureB)
{
	myEffect.Parameters["TextureA"].SetValue(textureA);
	myEffect.Parameters["TextureB"].SetValue(textureB);
}

I recommend doing it like this. It prevents issues like the one you ran into here @willmotil. You can also only set the register for the texture to make sure it resolves correctly for spritebatch (which sets the texture a t0), or other classes that use the texture register.

I only recommend setting the sampler by register when you do not explicitly declare a texture (hlsl implicitly declares a texture for each sampler in the corresponding register → t1 for s1, t2 for s2…). (Note that there’s a bug in MG making this method not work for now, I’ll get this fixed soon). In the other cases MonoGame generates an effect parameter by which you can set textures.

Since you don’t use the register directly for assigning textures in those cases you can let the compiler figure out the registers for you and not set them explicitly in the shader.

For examples of the recommended way to set shaders see Explaining a possible solution to the sampler/texture/effectparameter problems in MonoGame · GitHub

Part of that document will go in the docs once the sampler-only issue is resolved. See the following link for details Don't lose textures when applying effect by hifi · Pull Request #5288 · MonoGame/MonoGame · GitHub

Tl;dr: only set registers explicitly when

  1. You only declare samplers in your hlsl effect
  2. You know what you’re doing.
  3. You need both a register (because of classes like SpriteBatch) and an effectparameter. In this case when using the register, make sure you set the texture after applying your effectPasses!

I see thank you.

//_______________________________
// BasicShader .fx
//
#if OPENGL
#define SV_POSITION POSITION
// Gl shader level
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else 
// Dx shader level
#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1
#endif

// the textures

Texture2D TextureA;
sampler2D TextureSamplerA = sampler_state
{
    Texture = <TextureA>;
};

Texture2D TextureB;
sampler2D TextureSamplerB = sampler_state
{
    Texture = <TextureB>;
};

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float4 Color : COLOR0;
    float2 TexureCoordinate : TEXCOORD0;
};
struct VertexShaderOutput
{
    float4 Position : SV_Position;
    float4 Color : COLOR0;
    float2 TexureCoordinate : TEXCOORD0;
};

struct PixelShaderOutput
{
    float4 Color : COLOR0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;
    output.Position = input.Position;
    output.Color = input.Color;
    output.TexureCoordinate = input.TexureCoordinate;
    return output;
}

// using both textures 
PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
    PixelShaderOutput output;
    // test
    float4 A = tex2D(TextureSamplerA, input.TexureCoordinate) * input.Color;
    float4 B = tex2D(TextureSamplerB, input.TexureCoordinate) * input.Color;
    A.a = B.a;
    output.Color = A;
    return output;
}

// using a single texture
//PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
//{
//    PixelShaderOutput output;
//    output.Color = tex2D(TextureSampler, input.TexureCoordinate) * input.Color;
//    return output;
//}

technique BlankTechnique
{
    pass
    {
        VertexShader = compile VS_SHADERMODEL VertexShaderFunction();
        PixelShader = compile PS_SHADERMODEL PixelShaderFunction();
    }
}

.

in load

            blankEffect = Content.Load<Effect>("BasicShader");
            blankEffect.Parameters["TextureA"].SetValue(MyContentLoadedImageA);
            blankEffect.Parameters["TextureB"].SetValue(MyContentLoadedImageB);
            blankEffect.CurrentTechnique = blankEffect.Techniques["BlankTechnique"];