Bright pass filter

Started by
3 comments, last by sordid 18 years, 9 months ago
Ok, so I've been sitting here for about 3 hours looking over this portion of shader code (it's in HLSL but that's irrelevant), and I can't figure out one portion of it. I'd prefer to understand it rather than just throwing it in. It's for the bright pass step of a fake HDR post processing filter, and the code I'm looking at is from the DX SDK (PP_ColorBrightPass.fx in the PostProcessing sample)

static const float Luminance = 0.08f;
static const float fMiddleGray = 0.18f;
static const float fWhiteCutoff = 0.8f;

//-----------------------------------------------------------------------------
// Pixel Shader: BrightPassFilter
// Desc: Perform a high-pass filter on the source texture
//-----------------------------------------------------------------------------
float4 BrightPassFilter( in float2 Tex : TEXCOORD0 ) : COLOR0
{
    float3 ColorOut = tex2D( g_samSrcColor, Tex );

    ColorOut *= fMiddleGray / ( Luminance + 0.001f );
    ColorOut *= ( 1.0f + ( ColorOut / ( fWhiteCutoff * fWhiteCutoff ) ) );
    ColorOut -= 5.0f;

    ColorOut = max( ColorOut, 0.0f );

    ColorOut /= ( 10.0f + ColorOut );

    return float4( ColorOut, 1.0f );
}



Now, I take it the variable 'Luminance' is some "guess" on the average luminance of the entire screen pixels based on probably some statistical data or a 6 pack of Guiness. I've seen some similarities between this code and Reinhard's paper from SIGGRAPH. It also appears in http://www.cs.virginia.edu/~gfx/pubs/tonemapGPU/itm.pdf Anyway, the first multiplication I see there indicates that they're tone mapping to some target luminance (fMiddleGray) based on a "guess" of an average luminance value (Luminance). This is probably because they don't want to waste time calculating an actual average luminance for the entire screen. The subtraction of 5 in the third line and the max() in the fourth line indicates to me that it's killing off the low intensity pixels. The last line seems to map it back into a range of 0..1 (not 100% sure why they would use 10 rather than some other number.. probably because of the range 0..256 and 10 provides a good distribution to the lower end. Anybody know for sure?) But my question lies in this line: ColorOut *= ( 1.0f + ( ColorOut / ( fWhiteCutoff * fWhiteCutoff ) ) ); In short, what the hell? Is it painfully obvious, but I've just been looking at it for too long?
Advertisement
You should take a look at the sample "HDRLighting" which uses almost the same shader to fake hdr. DirectX9SDK's help also contains a lot of explanations (see HDR Lighting Sample). To be short, Luminance is calculated in the HDRLighting sample (maybe not in the PostProcess one). You have guessed true for the 5.0f subtraction, and the division with 10.0f is here to map to the 0..1 range. If you augment the value 10, it separates more clearly lights from illuminated scene objects, as explained in the help page. I am not sure about what your line does though.
Yeah, I looked through the HDR Lighting sample. I googled, I went everywhere I could to find something similar to this.

The HDR Lighting sample doesn't even use that line. Possibly because they actually do a full-texture calculation for the average luminance. The bright pass filter is the same, except for the mystery line.

When I remove that line, it appears that its function is to define some more higher-luminance pixels, not just the white from the sky in the PP sample. Doesn't pick up a lot of the brighter reddish-biege colours from some of the buildings, or the entire windows.
I'm still trying to construct a rationalize explanation for it though.. argh.
If you expand it, it comes to:

ColorOut = ColorOut + ColorOut^2 / fWhiteCutoff^2;

This adds a quadratic element to the output color. If the range of ColorOut is from 0 .. fWhiteCutoff first, then the range will be from 0 .. 2*fWhiteCutoff after this line. (I'm just guessing at the ranges).

The effect of this is to create some form of non-linear tone mapping.
enum Bool { True, False, FileNotFound };
Yes! I see it now. You sparked an idea to create a full-screen gradient texture map and see what the filter does to it. It all makes perfect sense.

I never think to expand an equation when it's not on paper.
Thanks, hplus.

This topic is closed to new replies.

Advertisement