How can I add a custom shader to a Monogame Windows Phone project?

I created the Effect1.mgfxo file, but I don’t know how to load it in my game. How can I load it?

I have a slightly odd setup and in my LoadContent have

   #if RESOURCEFILES
        BinaryReader Reader = new BinaryReader(File.Open(@"..\\..\\..\\Content\\Effects.mgfxo", FileMode.Open));
    #else
        Assembly assembly = Assembly.GetExecutingAssembly();
        BinaryReader Reader = new BinaryReader(assembly.GetManifestResourceStream("Effects.mgfxo"));
    #endif
        _Effect = new Effect(GraphicsDevice, Reader.ReadBytes((int)Reader.BaseStream.Length));

which gives 2 ways either from file or embedded resource.

I get an error message in this line:

Assembly assembly = Assembly.GetExecutingAssembly();
The type or namespace name ‘Assembly’ could not be found (are you missing a using directive or an assembly reference?)

Is it not possible to load the shader like this?

Effect = Content.Load(“Effect1.mgfxo”);

You need to add Assembly’s namespace which from the top of my head is in the reflection namespace. I said I was doing things differently and yes you should be able to do something like Content.Load although I’d guess it’s just a nicer way of using GetManifestResourceStream.

The screen of my emulator is always black if I run this code and I get no error message. Why is the code not working? Why is the screen always black if I try to run my shader?

public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
private Texture2D back;
public Texture2D shockwave;
private RenderTarget2D finalImage;
private RenderTarget2D distortionMap;
private Effect distortionEffect;
private Vector2 Touchpoint;

    public Game1() 
    { 
        graphics = new GraphicsDeviceManager(this); 
        Content.RootDirectory = "Content"; 
    } 
    protected override void Initialize() 
    { 
        base.Initialize(); 
    } 
    protected override void LoadContent() 
    { 
        TouchPanel.EnabledGestures = GestureType.Tap; 
        spriteBatch = new SpriteBatch(GraphicsDevice); 
        back = Content.Load<Texture2D>("background"); 
        shockwave = Content.Load<Texture2D>("shockwavesprite"); 
        finalImage = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height); 
        distortionMap = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height); 
        distortionEffect = Content.Load<Effect>("Effect1.mgfxo"); 
    } 
    protected override void Update(GameTime gameTime) 
    { 
        while (TouchPanel.IsGestureAvailable) 
        { 
            GestureSample gs = TouchPanel.ReadGesture(); 
            switch (gs.GestureType) 
            { 
                case GestureType.Tap: 
                    Touchpoint = new Vector2(gs.Position.X, gs.Position.Y); 
                    break; 
            } 
        } 
        base.Update(gameTime); 
    } 
    protected override void Draw(GameTime gameTime) 
    { 
        GraphicsDevice.Clear(Color.CornflowerBlue); 
        GraphicsDevice.SetRenderTarget(finalImage); 
        GraphicsDevice.Clear(Color.CornflowerBlue); 
        spriteBatch.Begin(); 
        spriteBatch.Draw(back, Vector2.Zero, Color.White); 
        spriteBatch.End(); 
        GraphicsDevice.SetRenderTarget(distortionMap); 
        GraphicsDevice.Clear(Color.Black); 
        spriteBatch.Begin(); 
        spriteBatch.Draw(shockwave, new Vector2(Touchpoint.X - (shockwave.Width / 2), Touchpoint.Y - (shockwave.Height / 2)), Color.White); 
        spriteBatch.End(); 
        GraphicsDevice.SetRenderTarget(null); 
        distortionEffect.Parameters[0].SetValue(finalImage); 
        distortionEffect.Parameters[1].SetValue(distortionMap); 
        spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, distortionEffect); 
        spriteBatch.Draw(finalImage, Vector2.Zero, Color.White); 
        spriteBatch.End(); 
        base.Draw(gameTime); 
    } 
}

The sort of stuff I was/am doing is to assume the shader isn’t working, so to check it, write a shader which returns a single color like red. If your screen goes red then you know the shader is being called and can then try working backwards by adding in more of your shader code. If the screen is still black then work the other way by assuming the c# code is wrong and not setting the shader up properly.

I tried to load a shader with your code, but I always get the following error message in this line:

BinaryReader Reader = new BinaryReader(assembly.GetManifestResourceStream(“Effect1.mgfxo”));
An exception of type ‘System.ArgumentNullException’ occurred in mscorlib.ni.dll but was not handled in user code
Additional information: Value cannot be null.
If there is a handler for this exception, the program may be safely continued.

What is wrong? How can I load the file?

My project: http://speedy.sh/CHVbj/GameName1.rar

My code:

#if RESOURCEFILES
BinaryReader Reader = new BinaryReader(File.Open(@“…\…\…\Content\Effect1.mgfxo”, FileMode.Open));
#else
Assembly assembly = Assembly.GetExecutingAssembly();
BinaryReader Reader = new BinaryReader(assembly.GetManifestResourceStream(“Effect1.mgfxo”));
#endif
distortionEffect = new Effect(GraphicsDevice, Reader.ReadBytes((int)Reader.BaseStream.Length));

When you build your project the mgfx file needs to be added as an “Embedded Resource” as part of the build. You should be able to use a tool like ILSpy to look inside your exe to see whether the file has been added correctly.

1 Like