Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


Best way to filter for a bloom effect


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
11 replies to this topic

#1 ic0de   Members   -  Reputation: 869

Like
0Likes
Like

Posted 11 October 2012 - 05:13 PM

So I have had a bloom effect implemented for some time but I just haven't been able to make it look right. I start my effect by filtering out the really bright parts then I do a two pass Gaussian blur and blend the blurred bright stuff with the original image. I have come to the conclusion that to make it look right I need to tweak how I decide what is bright so far I have two ways neither of which work well. My code is written in GLSL but this really applies to HLSL and cg as well. Anyway the first way goes like this:
if(sample.r > level)
{
  sample.r = 1.0;
}
else
{
  sample.r = 0.0;
}


if(sample.g > level)
{
  sample.g = 1.0;
}
else
{
  sample.g = 0.0;
}

if(sample.b > level)
{
  sample.b = 1.0;
}
else
{
  sample.b = 0.0;
}
The problem with this method is that It will always glow either red, green or blue. For example a bright purple would glow red.

Method 2:

if((0.2126*sample.r) + (0.7152*sample.g) + (0.0722*sample.b) > level)
{
  sample.r = 1.0;
  sample.g = 1.0;
  sample.b = 1.0;
}
else
{
  sample.r = 0.0;
  sample.g = 0.0;
  sample.b = 0.0;
}
This method works by determining the overall brightness (luminance?). But it never seems to glow any color but white.

So I developed two methods but neither seem to work right. Does anyone have any methods that they have used successfully? Or any suggestions on how to improve mine?

Edited by ic0de, 12 October 2012 - 05:59 AM.

you know you program too much when you start ending sentences with semicolons;


Sponsor:

#2 luca-deltodesco   Members   -  Reputation: 637

Like
0Likes
Like

Posted 12 October 2012 - 02:56 AM

Why are you multiplying the colour values by 2 in your second approach? That is probably why you're ending up with white glows since after saturation of the values you're likely ending up with white in most cases.

#3 ic0de   Members   -  Reputation: 869

Like
0Likes
Like

Posted 12 October 2012 - 05:59 AM

Why are you multiplying the colour values by 2 in your second approach? That is probably why you're ending up with white glows since after saturation of the values you're likely ending up with white in most cases.


Sorry that's a typo I was just testing something and accidentally posted the wrong shader. I updated it in my post but obviously it will still set everything to white. How do you suggest I brighten it without making white?

you know you program too much when you start ending sentences with semicolons;


#4 bwhiting   Members   -  Reputation: 785

Like
0Likes
Like

Posted 12 October 2012 - 07:52 AM

Don't set them all to 1 for a start.

You could multiply them by a small factor i.e. 1.2 to make them brighter but consider that if you are adding the result to the buffer then you would probably want to de-brighten (great wordage) them first.

I think in the past I have just run a threshold, then blur, then a multiply down, then composite with an add

#5 ic0de   Members   -  Reputation: 869

Like
1Likes
Like

Posted 12 October 2012 - 01:31 PM

I figured it out on my own and I must say It looks beautiful (although the effect seems to be fighting with my ssao). Anyway here is my solution.
if((0.2126*sample.r) + (0.7152*sample.g) + (0.0722*sample.b) > level)
{
  float brightenRatio = 1.0 / max(max(sample.r, sample.g), sample.b);
  sample.r *= brightenRatio;
  sample.g *= brightenRatio;
  sample.b *= brightenRatio;
}
else
{
  sample.r = 0.0;
  sample.g = 0.0;
  sample.b = 0.0;
}

The largest component ends up being 1.0 and the smaller components maintain the same ratio hence obtaining the same colour only brighter.

Edited by ic0de, 12 October 2012 - 01:32 PM.

you know you program too much when you start ending sentences with semicolons;


#6 kalle_h   Members   -  Reputation: 1471

Like
1Likes
Like

Posted 12 October 2012 - 03:45 PM

(0.2126*sample.r) + (0.7152*sample.g) + (0.0722*sample.b)

Could be.

const vec3 luminance = vec3(0.2126, 0.7152, 0.0722);
float brightness = dot(lumiance * sample.rgb);


Your method lose information. Everything over threshold just goes as bright. You allways can brighten up the blurred bloom texture values when you are compositing image. Then you dont lost information and you get much more variety for bloom.

One easy trick is just multiply the color with itself and using treshold or smoothstep.

#7 ic0de   Members   -  Reputation: 869

Like
0Likes
Like

Posted 12 October 2012 - 04:56 PM

(0.2126*sample.r) + (0.7152*sample.g) + (0.0722*sample.b)

Could be.

const vec3 luminance = vec3(0.2126, 0.7152, 0.0722);
float brightness = dot(lumiance * sample.rgb);

Your method lose information. Everything over threshold just goes as bright. You allways can brighten up the blurred bloom texture values when you are compositing image. Then you dont lost information and you get much more variety for bloom.

One easy trick is just multiply the color with itself and using treshold or smoothstep.


Sorry I don't quite get what you're saying. Do you mean I use something like:
const vec3 luminance = vec3(0.2126, 0.7152, 0.0722);
float brightness = dot(lumiance * sample.rgb);

if(brightness > level)
{
	 // do the rest

Edited by ic0de, 12 October 2012 - 04:58 PM.

you know you program too much when you start ending sentences with semicolons;


#8 MrOMGWTF   Members   -  Reputation: 440

Like
0Likes
Like

Posted 12 October 2012 - 11:48 PM


if((0.2126*sample.r) + (0.7152*sample.g) + (0.0722*sample.b) > level)

{

    // just do nothing...

}

else

{

    discard;

}



#9 MJP   Moderators   -  Reputation: 11568

Like
2Likes
Like

Posted 13 October 2012 - 03:03 PM

The "best way" in my opinion is not to use a threshold at all. A step function is ugly and will cause aliasing. A more natural approach is to just use a lower exposure for your bloom pass, which will naturally subdue to darker areas while allowing brighter areas to remain visible in the end result.

#10 Hodgman   Moderators   -  Reputation: 30885

Like
0Likes
Like

Posted 13 October 2012 - 08:36 PM

In the threshold pass on my last project, we used an offset an a multiplier, e.g.
output = max(0, input-threshold)*scale;
Originally I was only had the scale variable, but the artists wanted a bit of extra control as to completely stopping the effect.

As with MJP's suggestion above, this ensures that there's no sudden point where your bloom texture jumps from zero up to some bright value.


BTW you should try an adopt a much more branchless style of programming when writing shaders compared to CPU code.
e.g. your different versions can have their if statements removed by using the step function along with multiplication:
//1
sample.rgb = step(vec3(level), sample.rgb);
//2
sample.rgb = vec3(step(level, dot(sample.rgb, vec3(0.2126, 0.7152, 0.0722))));
//3
float brightenRatio = 1.0 / max(max(sample.r, sample.g), sample.b+0.00000001);
brightenRatio *= step( level, dot(sample.rgb, vec3(0.2126, 0.7152, 0.0722)) );
sample.rgb *= brightenRatio;

Edited by Hodgman, 13 October 2012 - 08:38 PM.


#11 pachesantiago   Members   -  Reputation: 180

Like
1Likes
Like

Posted 15 October 2012 - 12:06 PM

hy. im using this to in my bloom shader. is simple and it works really well

float4 color = tex2D( srcTex, IN.uv );
color = (-color + (pow(tex2D( srcTex, IN.uv ),Power) * Scale) )/Bias;
return color;
here's a screenshot using scale = 1.83, power = 4 and bias = 0.27
Posted Image
PS: this is HLSL, but i think it should be really similar

#12 pachesantiago   Members   -  Reputation: 180

Like
1Likes
Like

Posted 15 October 2012 - 12:09 PM

hy. im using this to in my bloom shader. is simple and it works really well


float4 color = tex2D( srcTex, IN.uv );
color = (-color + (pow(tex2D( srcTex, IN.uv ),Power) * Scale) )/Bias;
return color;
here's a screenshot using scale = 1.83, power = 4 and bias = 0.27
Posted Image
PS: this is HLSL, but i think it should be really similar

Sorry, didnt mention that the grayscale is another shader, is not part of the "bright pass"
Using colors:
Posted Image




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS