Encoding Float to RG/RGBA and Blending - Hard issue

Hey everyone,

Encoding a float value inside a RG or RGBA texture is very interesting and useful but it is also become quite useless when you use blending as the result and the values might be altered because of face overlapping.
Is there a way to avoid such issues ?

here is an example of a bad result when encoding depth on the red and green channels and just decoding it again in a post-process effect.

1907928--123077--bad.jpg

Thanks a lot !

There are unfortunately only two solutions:

  • Don’t use hardware interpolation. You have to manually read → decode → blend → encode → write
  • Use a texture format that can hold the value directly

Unfortunately, there’s no format in Unity free that can handle value directly… :frowning:
Could you develop your manual technic ?

It kind of depends on where you need to use it. Could you elaborate on what you’re currently doing and what you’re trying to achieve?

The aim is to retrieve a value from a shader. here is what I am doing.
Do my calculation inside a shader, rendering it inside a deactivated camera with replacement shaders, capturing the result inside a texture and distributing it to another shader.
I need to handle the Unity free limitation. The perfect solution would be to use a float texture but this is not available in Unity free so I need to encode it.
I also need to use blending and exp() in the last shader which makes the “steps” appear. The aim is to avoid those steps. But I am wondering if this is not caused by a precision issue…

Yeah that’s definitely caused by the lack of precision… 256 values simply isn’t enough… and unless you want to render each object one by one each with a separate camera, you can’t really blend the values manually. and that would be super slow.

Hmm… So you’re blending depth… and then using exp() on it. Sounds like volumetric fog to me :slight_smile:

I think there is a way, assuming the blend operation is addition / subtraction…
You should gain a bit more precision where you need it by writing the exp()-ed value directly… and since exp(a + b) = exp(a) * exp(b), then when writing a positive depth value you can do this: compute exp(-depth) to get a value between 0 and 1. To get even more precision, find the minimum and maximum depth you can have and expand the output to cover the full 0 to 1 range. Finally, use multiplicative blending instead of additive. That’s about all you can do I think.

This is a nice trick, I’ll test it but as you say, exp(a + b) = exp(a) * exp(b) so I need multiplicative blending but how about exp(a - b) ? And what about introducing an other value like exp(value * (a - b)) ?
This is not volumetric fog but very similar. :slight_smile:

Edit: After a small research it seams that exp(a-b) = exp(a) / exp(b) but how to do this with blending… Maybe something like (exp(a) / 1) * (1 / exp(b)) ?

Just exp(-a) * (1 / exp(-b)) should be enough