How to achieve a bloom effect on 2D textures?

I found the XNA Bloom Postprocess Sample and an implementation in this tutorial but it doesn’t seem to work.
The only thing I changed is the PixelShader version (to 4.0 from 2.0) due to a build error.

Is anyone aware of a working version of this or any other tutorial where the effect is achieved?
Thanks!

Following things needs to be changed:

Shader model - you´ve aready done it
POSITION0 to Sv_position0 in Vertex Input and Vertex output
Shaders for bloom extraction and bloom also miss COLOR0 input for Pixel Shader which is now required (renders black otherwise).

Also I dont remember how is sampler setup treated in that example, mono game have non XNA behavior when it comes to setting textures directly to samplers and not as material parameter.

Anyway, that example is good start, results are kinda poor. Sampling is done in kinda cheap manner. I don´t know what is your experience with shaders and how is your math, if you have some basic let me know and I will point you in direction of decent improvement (linear gauss, hdr bloom).

Thank you for the response.
Math I can manage, but I’m dealing with shaders for the first time and I still can’t wrap my head around it

.Can you elaborate on this? There is no POSITION0 in the code (isn’t this relevant only for vertex shaders?). Are you taking about the current example or in general?

As for the improvements - I need this for a fairly simple project, in fact very similar to the one in the tutorial above, so this will work out for me if I get it to work properly, but I will definitely follow up on this in the future (as soon as I get more comfortable with shaders and HLSL)

I´ve forgot that it uses default vertex shader, anyway it still applies for pixel shader… for example PS have look like this:

float4 PixelShaderFunction(float4 position : SV_Position, float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{

}

That was taken directly from modified, working BloomExtract.fx

2 Likes

My problem is that i can see the shader working but it loses the textures.
I just see the glow. Could it be a mfgx’s fault? I missed something in the shader?

This sounds to me as one Monogame issue. You can´t use set sampler directly, if you just assigned texture to specific sampler it won´t work. You have set it as parameter of specific .fx. This is clearly not XNA behavior.

Other then that it could be sampler declaration order / order in which they are used, that´s content pipeline bug which cause compiler to wrongly assume some samplers won´t be used at all therefore throwing them away.

If you can send some screenshots I might be able to help you, also if you can see only bloom check your combine shader.

Ehi Ravendarke, thank you!! :wink:
Ok, this is the bloom effect working on XNA/DirectX

This is the same shader on Monogame/OpenGL

As you can see, it show only the shader effect but culls all the textures.

The fx shaders are like that:

BloomExtract:

// Pixel shader extracts the brighter areas of an image.
// This is the first step in applying a bloom postprocess.

sampler TextureSampler : register(s0);

float BloomThreshold;


float4 PixelShaderFunction(float2 texCoord : TEXCOORD0) : COLOR0
{
    // Look up the original image color.
    float4 c = tex2D(TextureSampler, texCoord);

    // Adjust it to keep only values brighter than the specified threshold.
    return saturate((c - BloomThreshold) / (1 - BloomThreshold));
}


technique BloomExtract
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

BloomCombine:

// Pixel shader combines the bloom image with the original
// scene, using tweakable intensity levels and saturation.
// This is the final step in applying a bloom postprocess.

sampler BloomSampler : register(s0);
sampler BaseSampler : register(s1);

float BloomIntensity;
float BaseIntensity;

float BloomSaturation;
float BaseSaturation;


// Helper for modifying the saturation of a color.
float4 AdjustSaturation(float4 color, float saturation)
{
    // The constants 0.3, 0.59, and 0.11 are chosen because the
    // human eye is more sensitive to green light, and less to blue.
    float grey = dot(color, float3(0.3, 0.59, 0.11));

    return lerp(grey, color, saturation);
}


float4 PixelShaderFunction(float2 texCoord : TEXCOORD0) : COLOR0
{
    // Look up the bloom and original base image colors.
    float4 bloom = tex2D(BloomSampler, texCoord);
    float4 base = tex2D(BaseSampler, texCoord);
    
    // Adjust color saturation and intensity.
    bloom = AdjustSaturation(bloom, BloomSaturation) * BloomIntensity;
    base = AdjustSaturation(base, BaseSaturation) * BaseIntensity;
    
    // Darken down the base image in areas where there is a lot of bloom,
    // to prevent things looking excessively burned-out.
    base *= (1 - saturate(bloom));
    
    // Combine the two images.
    return base + bloom;
}


technique BloomCombine
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

Please note that i already tried to change the main function parameters as

(float4 pos : S_POSITION, float4 color : COLOR0, float2 texCoords : TEXCOORD0) : S_TARGET_OUTPUT

I tried few parameters combination without any result.

I’m using thi shader in the same way as it’s used in the microsoft sample (so i have two rendertargets that swaps between each other).

Thank you so much for your help :slight_smile:

Yep, this is exactly what I´ve said, you can´t assign textures directly to specific sampler in code anymore (in monogame), you have to set it as parameter otherwise that sampler is set to null. You are missing second texture in BloomCombine, here:

sampler BaseSampler : register(s1);

It is bug, I found quite long discussion between devs where they decided that this is the right behavior (while ofc it is quite opposite). Anyway, let´s fix it.

In BloomCombine:
-leave s0 as it is, but change s1 to be:

sampler BaseSampler : register(s1)
{ 
    Texture = (BaseTexture);  
    Filter = Linear;  
    AddressU = clamp;
    AddressV = clamp;
};

Now you have to assing texture to new parameter “BaseTexture” in code.

bloomCombineEffect.Parameters["BaseTexture"].SetParameter(RenderTargetWithBaseTexture);

Since you are working on app for low performance device don´t forget to cache your parameters later.

As such:

bloomBase = bloomCombineEffect.Parameters["BaseTexture"]; //somewhere in iniciliaziation of postprocess class so this happens only once

and then you can use each frame in drawloop:

bloomBase.SetParameter(RenderTargetWithBaseTexture);

WORKS LIKE A CHARM!!!

MY hero! You won a Steam key when the game will be released :smiley:

1 Like

I still can’t do it =(
I can’t even convert the .fx files to .mgfxo
Can you upload a sample project please???

Why do you want to convert them to .mgfxo and not .xnb?

I know this post is old, but I have been desperately trying to add a Gaussian blur to my game for the past 2 days. I am using monogame with Visual Basic instead of c#, and the “.setParemeters” function does not exist for me. I have everything else needed to set the texture in the .fx file. When I try to use “.setValue” instead it does not work with my texture2d that I am trying to blur. Any ideas?

I’m trying to convert the same tutorial this message started with and everything is black when bloom is enabled. I’m trying to figure out the changes required for the bloomCombine effect but failing.

In BloomComponent.cs, in the LoadContent() method the bloomCombineEffect is loaded like so:

bloomCombineEffect = Game.Content.Load(“Shaders/BloomCombine”);

The message above says I need to add somewhere:

bloomCombineEffect.Parameters[“BaseTexture”].SetParameter(RenderTargetWithBaseTexture);

When I add this though, I get the compile error that SetParameter is not a method. Also RenderTargetWithBaseTexture
is not a variable I have defined anywhere. Where do I get that from?

instead of SetParameter you need to use SetValue

if you are just looking for bloom in your game you can also use this thing: https://github.com/Kosmonaut3d/BloomFilter-for-Monogame-and-XNA

2 Likes

Same here mate, what on earth is “RenderTargetWithBaseTexture”. sceneRenderTarget seems like the only option but it just comes out upside down, half the size and with no bloom :frowning:

This worked for me. Many thanks

1 Like