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
\$\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.

| 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.