0
\$\begingroup\$

I'm converting an old XNA title to MonoGame and one of the HLSL fx files uses two textures. But no matter what I do, it only ever uses the screen texture while rendering the effect in MonoGame, or else draws nothing.

I can see in debug mode that I'm trying to pass in the correct textures in C#, plus it works correctly in the XNA version. So why is my shader only using the screen texture in Monogame?

HLSL

Texture2D ScreenTexture;
sampler2D ScreenSampler = sampler_state
{
    Texture = <ScreenTexture>;
};

Texture2D DistortionMap;
sampler2D OffsetSampler = sampler_state
{
    Texture = <DistortionMap>;
    AddressU = Clamp;
    AddressV = Clamp;
};

float4 PixelShaderFunction(float4 pos : SV_POSITION, float4 color1 : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    // Use the DistortionMap to alter the location of the ScreenSampler output.
    // DistortionMap's rg at a position correspond to that position's xy distortion.
    return tex2D(ScreenSampler, texCoord + (tex2D(OffsetSampler, texCoord).rg * 2 - 1));
}

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

C#

public static void Draw(SpriteBatch spriteBatch)
{
    // Update the Offsets map texture.
    UpdateVertices();

    // Set up the current render target to draw to the other render target
    Game1.RenderSetToA = !Game1.RenderSetToA;
    ThisGame.GraphicsDevice.SetRenderTarget(Game1.RenderSetToA ? Game1.RenderTargetA : Game1.RenderTargetB);
    RenderTarget2D renderTargetToDraw = Game1.RenderSetToA ? Game1.RenderTargetB : Game1.RenderTargetA;

    // Draw the old render target with the distortion effect to the new render target.
    DistortionEffect.Parameters["ScreenTexture"].SetValue(renderTargetToDraw);
    DistortionEffect.Parameters["DistortionMap"].SetValue(Offsets);
    spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, DistortionEffect);
    spriteBatch.Draw(renderTargetToDraw, Vector2.Zero, Color.White);
    spriteBatch.End();
}
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Figured it out, or at least figured out a workaround, in part with the help of this answer. It seems the tex2D method was not sampling the textures how I wanted it to with sampler2D samplers. I refactored the shader to use SamplerStates and the Texture2D.Sample function, like so:

Texture2D ScreenTexture;
Texture2D DistortionMap;
SamplerState Sampler;

float4 PixelShaderFunction(float4 pos : SV_POSITION, float4 color1 : COLOR0, 
float2 texCoord : TEXCOORD0) : COLOR0
{
    return ScreenTexture.Sample(Sampler, texCoord + (DistortionMap.Sample(Sampler, texCoord).rg * 2 - 1));
}

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

Note that I was able to do this with either one or two samplers, so I decided to just use one.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .