1
\$\begingroup\$

I'm trying to use this this tutorial in monogame, but the effect does not work, only renders a black screen. Everyhing by itself renders just fine, I looked at the render targets if they get drawn to, but when I try to apply the effect to them it only renders a black screen.

I converted the .fx file using 2MGFX, also tried loading it with the following code:

BinaryReader Reader = new BinaryReader(File.Open(@"Content\\Lighting.mgfx", FileMode.Open));
        lightingEffect = new Effect(GraphicsDevice, Reader.ReadBytes((int)Reader.BaseStream.Length)); 

also with

lightingEffect = content.Load<Effect>("Lighting.mgfx");

and also with

byte[] bytecode = File.ReadAllBytes("Content\\Lighting.mgfx");
        lightingEffect = new Effect(graphics.GraphicsDevice, bytecode);

They did not make a difference.

The .fx file contains the following:

sampler s0;
texture lightMask;
sampler lightSampler = sampler_state { Texture = <lightMask>; };

float4 PixelShaderFunction(float2 coords: TEXCOORD0) : COLOR0
{
    float4 color = tex2D(s0, coords);
    float4 lightColor = tex2D(lightSampler, coords);
    return color * lightColor;
}

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

And the monogame version of the game1.cs(Only the important stuff):

public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    Texture2D lightMask;
    Texture2D SquareGuy;

    RenderTarget2D lightsTarget;
    RenderTarget2D mainTarget;

    Effect lightingEffect;


    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        IsMouseVisible = true;
    }


     protected override void LoadContent()
     {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        lightMask = Content.Load<Texture2D>("lightmask");
        SquareGuy = Content.Load<Texture2D>("SquareGuy");
        // lightingEffect = content.Load<Effect>("Lighting.mgfx");
        /*
        byte[] bytecode = File.ReadAllBytes("Content\\Lighting.mgfx");
        lightingEffect = new Effect(graphics.GraphicsDevice, bytecode);
        */
        BinaryReader Reader = new     BinaryReader(File.Open(@"Content\\Lighting.mgfx", FileMode.Open));
        lightingEffect = new Effect(GraphicsDevice,     Reader.ReadBytes((int)Reader.BaseStream.Length)); 

        var pp = GraphicsDevice.PresentationParameters;
     //   pp.BackBufferHeight = 1024;
     //   pp.BackBufferWidth = 1024;
        lightsTarget = new RenderTarget2D(
            GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight);
        mainTarget = new RenderTarget2D(
            GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight);                            
     }          

     protected override void Draw(GameTime gameTime)
     {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here
        GraphicsDevice.SetRenderTarget(lightsTarget);
        GraphicsDevice.Clear(Color.Black);
        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Additive);
        spriteBatch.Draw(lightMask, new Vector2(0, 0), Color.White);
        spriteBatch.Draw(lightMask, new Vector2(100, 0), Color.White);
        spriteBatch.Draw(lightMask, new Vector2(200, 200), Color.White);
        spriteBatch.Draw(lightMask, new Vector2(300, 300), Color.White);
        spriteBatch.Draw(lightMask, new Vector2(500, 200), Color.White);
        spriteBatch.End();

        // Draw the main scene to the Render Target
        GraphicsDevice.SetRenderTarget(mainTarget);
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        spriteBatch.Draw(SquareGuy, new Vector2(100, 0), Color.White);
        spriteBatch.Draw(SquareGuy, new Vector2(250, 250), Color.White);
        spriteBatch.Draw(SquareGuy, new Vector2(550, 225), Color.White);
        spriteBatch.End();

        // Draw the main scene with a pixel
        GraphicsDevice.SetRenderTarget(null);
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
        lightingEffect.Parameters["lightMask"].SetValue(lightsTarget);
        lightingEffect.CurrentTechnique.Passes[0].Apply();
        spriteBatch.Draw(mainTarget, Vector2.Zero, Color.White);
        spriteBatch.End();

        base.Draw(gameTime);
    }
}

So the question is what do I need to change to make the effect work in monogame?

I tried it in XNA with this code and worked perfectly. I know almost nothing about HLSL, so I don't know if theres something wrong with the effect. I only changed the version thingy from ps_2_0 to ps_4_0_level_9_1. If I change it to ps_4_0_level_9_3 it still doesn't work. I read something about assigning textures from outside of the .fx here, but since I know so little about shaders I don't know if this is the problem.

\$\endgroup\$
  • \$\begingroup\$ Have you tried the last draw without the effect? GraphicsDevice.Clear often also clears the rendertargets. Just to be sure it's not the effect code but actually the rendertargets being cleared during the draw loop. \$\endgroup\$ – Felsir Oct 3 '15 at 11:45
  • \$\begingroup\$ @Felsir Yes, then it renders the renderTargets fine. \$\endgroup\$ – Rockar787 Oct 4 '15 at 8:11
1
\$\begingroup\$

I had this same problem last week. You need to add all the parameters to your PixelShaderFunction, or monogame will map registers incorrectly. Change your PixelShaderFunction parameters to be like this:

PixelShaderFunction(float4 pos : SV_POSITION, float4 color1 : COLOR0, float2 coords: TEXCOORD0)

Here is a more detailed explanation, where I got the answer: http://www.software7.com/blog/pitfalls-when-developing-hlsl-shader/

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.