[solved] - Problems with HLSL in Monogame

Ok, so I’m trying to get my head around HLSL in Monogame 3.4. Part of the problem is that many of the existing examples I find don’t work properly so I can’t figure out what I’m doing wrong and the error I’m getting isn’t helpful!

I’m trying to pass a texture and a palette texture to a pixel shader, at the moment I’m using SpriteBatch to do the drawing but eventually I’ll be applying it to polygons (hopefully). The texture is going in through the SpriteBatch draw method (I assume S0) whereas I need to pass the palleteImage through using Parameters, however when I try to do with the following I get a NullException on the SetValue as it doesn’t think there is a parameter. Any ideas? Or more to the point is there a working example that I can see as many of the existing pixel shader stuff I find doesn’t work on MonoGame 3.4!

HLSL

sampler TextureSampler : register(s0);

texture paletteImage;
sampler2D PaletteSampler = sampler_state {
	Texture = <paletteImage>;
};

float4 PixelShaderFunction(float4 position : SV_Position, float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
	float4 tex = tex2D(TextureSampler, texCoord);

	float2 coords = float2(0.5f, 0.5f);

	float4 palColour = tex2D(PaletteSampler, coords);

	return tex * color;
}

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

Draw code

 GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            effect.CurrentTechnique.Passes[0].Apply();
            effect.Parameters["paletteImage"].SetValue(paletteImage);
            // draw here


            spriteBatch.Draw(texture, new Rectangle(10, 10, texture.Width * 3, texture.Height * 3), Color.White)
            spriteBatch.End();

The exception occurs at SetValue, as far as I can tell the HLSL is fine, but something is amiss… I’ve noticed that if it doesn’t think a parameter is being used it throws an error (for example, I tried passing in a colour but it wasn’t until I used that colour in the HLSL code that it was accepted… is this the same thing?)

try using ps_4_0_level_9_1 instead of ps_4_0 for Windows based HLSL… if you are using the shader on OpenGL you will need to use ps_2_0 I think.

Sadly didn’t do anything. Thanks for trying though! I’ll keep trying different things but any other ideas welcome!

Here is a sample-shader that definitely works in my setup on OpenGL and windows-projects:

/* 
A wiggle effect distorts the source image using sine and cosine wave-functions.
*/

sampler ColorMapSampler : register(s0);

float timer;
float factor;

// color is the tint-color given by the drawSprite-call.
// Tex are the coordinates of the texture that are currently being calculated.
// return value was previously color0
float4 PixelShaderWiggle(float4 pos : SV_POSITION, float4 color : COLOR0, float2 texCoord : TEXCOORD0) : color0
{
	texCoord.x += sin(timer + texCoord.x * 10) * 0.01f * factor;
	texCoord.y += cos(timer + texCoord.y * 10) * 0.01f * factor;
	
	color *= tex2D(ColorMapSampler, texCoord);
	return color;
}


technique wiggle
{
	pass P0
	{
		#if SM4
			PixelShader = compile ps_4_0_level_9_1 PixelShaderWiggle();
		#elif SM3
			PixelShader = compile ps_3_0 PixelShaderWiggle();
		#else
			PixelShader = compile ps_2_0 PixelShaderWiggle();
		#endif
	}
}
1 Like

Easy explanation, aggressive compiler. PalColour isn´t ever used (ofc in that case same goes for whole sampler) in way to affect return value, thus compiler gets completely rid of it and that cause null exception (as your parameter doesn´t exist at all in compiled version).

1 Like

My apologies in not replying, Christmas is hard work! Can confirm this is the reason… But damn that’s a very aggressive compiler that it removes things like that!

You can try to set compiler to compile shaders in “debug” mode, but honestly it seems slightly broken (in terms of Monogame pipeline, debug is normally used for shaders profiling).