Glow with forward rendering without two passes/MRT?

I am trying to implement controllable bloom. By controllable I mean bloom that can be requested even for non-bright pixels by adding the bloom value into a model's texture channel. To do this I need to somehow pass this value (the strength of the bloom for the current pixel) into the bloom post-processor. The most obvious choice would be storing it in the alpha channel, but I use alphablending for every model I draw so for me this is not an option. A quick and dirty solution is to use MRT, render to two textures and then recombine them into one which is a huge waste of memory and speed. Another solution could be to render the scene twice: once for the color and alpha components and second for the bloom components - that is the by-the-book method I find on every internet page. Even when rendering into a smaller RT this is still an overkill.

Another thing I thought about was using YCbCr encoding and then simply increasing Y to order bloom, but I always get a green-ish image after decoding (even if I encode-decode in the very same shader, line after line). Here is the encode-decode operations I did:

inline float3 RGBtoYCbCr(float3 color)
{
float3 YCbCr;
YCbCr.r = color.r*0.299f + color.g*0.587f + color.b*0.114f;
YCbCr.g = 0.5f + (-color.r*0.168f - color.g*0.331f + color.b*0.5f);
YCbCr.b = 0.5f + (color.r*0.5f - color.g*418 - color.b*0.081f);

return YCbCr;
}

inline float3 YCbCrtoRGB(float3 color)
{
float3 RGB;
RGB.r = color.r+1.402*(color.b-0.5f);
RGB.g = color.r-0.344*(color.g-0.5f)-0.714*(color.b-0.5f);
RGB.b = color.r+1.772*(color.g-0.5f);

return RGB;
}

{
...
output.COLOR.rgb = saturate(output.COLOR.rgb);

output.COLOR.rgb = RGBtoYCbCr(output.COLOR.rgb);
output.COLOR.rgb = YCbCrtoRGB(output.COLOR.rgb);
}


So I wanted to ask if anyone knows a way to do it in one pass without MRT and (if possible) by still rendering an HDR image?

• I'm confused - you say at the top you want to be able to request bloom even on non-bright pixels, but then you are talking about HDR rendering and applying bloom to bright pixels? Which is it? – Nathan Reed Nov 24 '13 at 21:26
• Also, why are you so opposed to MRT? That's the usual way to do this sort of thing, e.g. in deferred shading. If you only need one channel from the second RT, then make it R8 format. MRT is pretty efficient, unless you're on a mobile device. – Nathan Reed Nov 24 '13 at 21:28
• I ment that instead of having a brightness treshhold, I want to specify myself which pixels should end up in the about-to-be-blured texture and how bright they should be there (hense the value). I am curently switching to indexed forward renderer from deferred renderer so I am planning not to use MRT at all. Partially because I want to use MSAA, so no MRT is not an option. Maybe you know a good way to encode two variables into a floating point 16-bit channel? My attemts only resulted in precision loss usually due to the fact that I don't understand how floats work in textures. – cubrman Nov 25 '13 at 7:02
• I guess you are using D3D9 then, since you say you can't use MSAA with MRT? FYI, in D3D10-11 you can combine them. In principle it should be possible to pack two 8-bit values in a 16-bit float, but it sounds pretty difficult, and I didn't find any working implementation with a little googling. With a 16-bit integer texture it would be a lot simpler, but I don't think D3D9 supports that (D3D10-11 do, though). – Nathan Reed Nov 25 '13 at 8:09
• Ok ok I know how good D3D10-11 is, but yes I am stuck on D3D9, why? Because I am a complete newbie in graphics and programming in general, thw we are coding in XNA. And yes I know packing is simple with integer textures but indeed I want to avoid 16 bit integer textures as I personally saw how instead of using this texture the game used R10G10B10A2 when I launched it on an old GPU (I used it for lighting so it was clearly visible). I guess the worst case scenario for me would be to render the scene twise, but again I want to avoid it as our rendering code is quite iterleaved with updating... – cubrman Nov 25 '13 at 8:28