[Solved] Shader working in OpenGL but not in WinDX

Hi all,

I’ve implemented a pixel shader that takes a texture and uses it as a mask so that I can render a diagonal split-screen. This is working fine in an OpenGL project for windows, but does not work for the DirectX version and I do not know where to look next to try and solve it.

It’s pretty straight forward. I’ve added some test repos here: Google Drive

C# code

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        private Effect alphaEffect;
        private RenderTarget2D renderTargetA;
        private RenderTarget2D renderTargetB;
        private Texture2D pixel;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.GraphicsProfile = GraphicsProfile.HiDef;
            graphics.PreferredBackBufferWidth = 1920;
            graphics.PreferredBackBufferHeight = 1080;
            graphics.ApplyChanges();

            Content.RootDirectory = "Content";
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            alphaEffect = Content.Load<Effect>("AlphaStencil");

            renderTargetA = new RenderTarget2D(GraphicsDevice, 1920, 1080);
            renderTargetB = new RenderTarget2D(GraphicsDevice, 1920, 1080);

            pixel = CreateWhitePixel(graphics.GraphicsDevice);
        }

        protected override void Draw(GameTime gameTime)
        {
            // left half
            graphics.GraphicsDevice.SetRenderTarget(renderTargetA);
            graphics.GraphicsDevice.Clear(Color.Fuchsia);

            // right half
            graphics.GraphicsDevice.SetRenderTarget(renderTargetB);
            graphics.GraphicsDevice.Clear(Color.Teal);

            graphics.GraphicsDevice.SetRenderTarget(null);
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

            
            alphaEffect.Parameters["MaskWidth"].SetValue(1920f);
            alphaEffect.Parameters["MaskHeight"].SetValue(1080f);

            alphaEffect.Parameters["BaseTextureWidth"].SetValue(1920f);
            alphaEffect.Parameters["BaseTextureHeight"].SetValue(1080f);

            // render masked left half
            alphaEffect.Parameters["InputTexture"].SetValue(renderTargetA);
            alphaEffect.Parameters["MaskTexture"].SetValue(Content.Load<Texture2D>("CombatSplitStencil_A"));

            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, alphaEffect);
            spriteBatch.Draw(renderTargetA, graphics.GraphicsDevice.Viewport.Bounds, Color.White);
            spriteBatch.End();

            // render masked right half
            alphaEffect.Parameters["InputTexture"].SetValue(renderTargetB);
            alphaEffect.Parameters["MaskTexture"].SetValue(Content.Load<Texture2D>("CombatSplitStencil_B"));

            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, alphaEffect);
            spriteBatch.Draw(renderTargetB, graphics.GraphicsDevice.Viewport.Bounds, Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }

        public static Texture2D CreateWhitePixel(GraphicsDevice GraphicsDevice)
        {
            var _whiteTex = new Texture2D(GraphicsDevice, 1, 1);
            _whiteTex.SetData(new[] { Color.White });

            return _whiteTex;
        }

And here’s the pixel 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

    struct VsInputQuad
    {
        float4 Position : POSITION0;
        float4 Color : COLOR0;
        float2 TexureCoordinateA : TEXCOORD0;
    };

    struct VsOutputQuad
    {
        float4 Position : SV_Position;
        float4 Color : COLOR0;
        float2 TexureCoordinateA : TEXCOORD0;
    };

    struct PsOutputQuad
    {
        float4 Color : COLOR0;
    };

    Texture2D InputTexture;
    sampler InputSampler
    {
        Texture = <InputTexture>;
        AddressU = CLAMP;
        AddressV = CLAMP;
        MagFilter = POINT;
        MinFilter = POINT;
        Mipfilter = POINT;
    };

    Texture2D MaskTexture;
    sampler MaskSampler
    { 
        Texture = <MaskTexture>;
        AddressU = CLAMP;
        AddressV = CLAMP;
        MagFilter = POINT;
        MinFilter = POINT;
        Mipfilter = POINT;
    };

    float MaskWidth = 0.0;
    float MaskHeight = 0.0;
    float MaskLocationX = 0.0;
    float MaskLocationY = 0.0;
    float BaseTextureLocationX = 0.0;
    float BaseTextureLocationY = 0.0;
    float BaseTextureWidth = 0.0;
    float BaseTextureHeight = 0.0;

    PsOutputQuad AlphaStencilPs(VsOutputQuad input)
    {
    float maskPixelX = input.TexureCoordinateA.x * BaseTextureWidth + BaseTextureLocationX;
    float maskPixelY = input.TexureCoordinateA.y * BaseTextureHeight + BaseTextureLocationY;
    float2 maskCoord = float2((maskPixelX - MaskLocationX) / MaskWidth, (maskPixelY - MaskLocationY) / MaskHeight);
    float4 bitMask = tex2D(MaskSampler, maskCoord);
    float4 tex = tex2D(InputSampler, input.TexureCoordinateA);

    PsOutputQuad output;
    output.Color = tex * (bitMask.a);
    return output;
    }

    technique AlphaStencil
    {
        pass Pass1
        {
            PixelShader = compile PS_SHADERMODEL AlphaStencilPs();
        }
    }

I’m using Monogame 3.7.1, project is set to HiDef, content is built for the appropriate projects, is there something I’m missing? The code is the same between the DirectX and the OpenGL projects.

Many thanks in advance!

Uuurrrghhh - figured it out. Related to this issue http://community.monogame.net/t/order-of-tex2d-in-shader/8720/26

So simply moving float4 tex = tex2D(InputSampler, input.TexureCoordinateA); to be the first line in the shader fixed it.

1 Like