create a rendertarget texture in D3DFMT_A16B16G16R16 format and render the scene to it. My shaders still outputs a color between 0 and 1 but the precision is a 32bit float for each channel. That 32bit float output must then be truncated down to fit in a 16bit channel in the texture render target?Yes, your shaders always output 32bit floats, which are then truncated to the precision of the render-target.
The colors are still between 0 and 1 in both situations but in two different precisions, making room for smoother color transients. So even with 100 light sources the intensity will never go beyond the value 1.0f?D3DFMT_A16B16G16R16 still only stores values from 0-1, but it does so in increments of 1/65536th instead of the usual increments of 1/256th.
With this format, you have to be careful with your lighting values so that they never reach 1.0f, because if they do, then you won't be able to represent anything brighter, and you get strange results where that happens.
D3DFMT_A16B16G16R16F is probably what you want -- it stores floating point numbers, but in the compact "half float" format, instead of full 32-bit floats. This lets you store numbers from around 0-65519, with a decent amount of fractional precision. This means that if you've got 10 lights with brightness of '100' overlapping, then there will be no clamping of the result. You'll be able to store 1000.0f in the render-target!
I thought that from reading guides that the unexposed value from the HDR texture would be between 0 and infinity..... The K is the Luminance adaption value.As above, I'd recommend using the 16F format so that your HDR texture is between 0 and big-enough-to-pretend-it's-infinity ;)
If you do use a format that's between 0 and 1, you can use some kind of hand-picked multiplier value as your brightest HDR value. e.g. if you use "unexposed * 1000" in your tone-mapper, and "return output * 0.001" in your lighting shaders, then your render target is basically storing values from 0 to 1000, in increments of 1/65536.
Can K be obtained by having a global variable instead of another render target that each fragment adds its Log2(exposed) value to?In D3D9, shaders can't write to shared global variables like that. The "unordered access view" makes this possible in D3D11 only.
To get that Bloom effect ... This sums up to 3 or 4 passes?Usually you'd do your "darken" pass during down-sampling, seperate from the blurring. The reason is, that you want the input texture to the blur to be low-res, as well as the output texture (otherwise you waste bandwidth).
1) render HDR scene
2) output Log luminance (and mipmap or downsample to 1x1)
3) downsample HDR scene and apply a darkening factor
4) blur downsampeld scene vertically
5) blur the previous horizontally
6) sum together the HDR scene and the blur-result, and tone-map the result (output as 0-1 to an 8-bit target)
In my last game, we did it a bit differently though for performance reasons (we were targeting old GPUs where 64bpp textures were slow):
1-5) as above, except #3's "darkening factor" is a tone-mapper (outputting 0-1 to an 8-bit target), and 4/5 are done in 8-bit.
6) tone-map the HDR scene (output as 0-1 to an 8-bit target)
7) screen-blend the blur-result over the scene