HDR IBL shaders / lighting

I’m possibly looking at doing some car stuff and of course you need HDR IBL to create car stuff that looks any good…

From what I can tell so far the best you can do in 3.5 is use a ldr cubemap which frankly looks bad and is not suitable for what I’m after…

Will unity 4 be able to do this kind of thing? Ideally some kind of blinn shader that can be lit with a HDR IBL map and use a lightmap for shadowing…

I have similar problem. Possible solution is to create custom shader that multiplies texture colors with some value bigger than 1. Other solution is to create RGBE texture in some external editor. RGBE format assumes that E component(Alpha) is exponent. Due to human eye physiology this format is acceptable for most cases and still it is not 16 or 32 bit color so unity will support it correctly. This solution also needs custom shader that will apply exponent to RGB value.

That’s really poor i can’t see how unity can be used for any product visualisation purposes in it’s current state…

The solution that ufo_driver suggested is quite viable (after some tweaks). One thing to note is that all the channels (RGB and A) have values in the [0;1] range, so if you multiply them together you will end up with a value not bigger than 1. That leads us to RGBM, which we use on non-mobile plaltforms to encode HDR values for lightmaps, that are then stored in 32bpp (and by default DXT5 compressed).

The decoding: (kRGBMMaxRange * texture.a) * texture.rgb – we use 8.0 as kRGBMMaxRange
The encoding: see details (and a link to a gist containing source code) in my RGBM encoding comparison.

That said, we will look into ways of importing HDR cubemaps into Unity. It would help if you would post that idea on Unity Feedback, as it getting some votes might bump it on our priority list.

There is one more way. It is possible to create standard texture with four 8-bit channels and put luminance into them. Then it can be taken back

float lum = color.r * 16581375.0 + color.g * 65025.0 + color.b * 255.0 + color.a

lum will have really big range acceptable for any HDR task. Multiplier values still need to be checked

What you probably meant was to store the multiplier (luminance if you will), scaled down into the [0;1) range, in another RGBA texture and encode/decode it as follows (extracted from UnityCG.cginc):

// Encoding/decoding [0..1) floats into 8 bit/channel RGBA. Note that 1.0 will not be encoded properly.
inline float4 EncodeFloatRGBA( float v )
{
	float4 kEncodeMul = float4(1.0, 255.0, 65025.0, 160581375.0);
	float kEncodeBit = 1.0/255.0;
	float4 enc = kEncodeMul * v;
	enc = frac (enc);
	enc -= enc.yzww * kEncodeBit;
	return enc;
}
inline float DecodeFloatRGBA( float4 enc )
{
	float4 kDecodeDot = float4(1.0, 1/255.0, 1/65025.0, 1/160581375.0);
	return dot( enc, kDecodeDot );
}

This is less practical than RGBM as it requires sampling two cubemaps at once (one with chromaticity, the other with luminance) and then multiplying by the value the luminance was scaled by.

I don’t know if this is mistake or not, but code you posted here has number 160581375.0 and calc says that 255 * 255 * 255 = 16581375 (without zero after 16)

Thanks for the feedback, I’m no shader writer though I was hopping there would be some pre-built material I could just use…

Interestingly, this value is not a mistake: “And yes, the last component (the one that uses 160581375) is pretty much meaningless.” from Aras’ Encoding Floats to RGBA, Redux.

we found a work around solution for that, which take advantage of unity’s vertex render path. First, insert the RGBM encode code into vertex-lit shaders for objects that are visible to cubemap renderer. Then add in the decode code for reflective objects such as car paint and glasses. vola~

Looking great, gtpdzbiz!

Using the Vertex Lit path for reflections is a very good idea. We also used that in the Dark Unity demo – just showing the big objects with lightmaps only.

well that is kinda stunning Quality and of course a really tricky Technic to Use Vertex Lit Path !!
the overal quality is amazing thing !
its so nice job “gtpdzbiz”

sir please check your PM’s

Your solution looks great!

Could you explain more on how you take advantage of Unitys the vetext render path, and how you encode the RGBM data into a vertex lit shader?

Thanks David.

Could you elaborate exactly why ‘vertex lit path’ is relevant in this? What gtpdzbiz seems to be doing is rescale a higher range color value to a standard [0,1] range for each component while rendering it to a cubemap . In the reflection shader this seems to be remultiplied by the inverse scaling factor. I can’t seem to fathom why using Vertex Lit path is clever and why I can figure it out :slight_smile: Cheers!

I’m necro-ing an old thread… but…:

To anyone that cares, I created a feature request in the feedback page. If you throw some votes in, it would be awesome:

http://feedback.unity3d.com/unity/all-categories/1/hot/active/hdr-cubemaps

Definitely voting for this.

I’ve been writing some IBL tools and resorted to RGBM cubemaps to get my high dynamic fix. It works but has some quality and range issues, no substitute for float-16 support.

A shameless plug: http://forum.unity3d.com/threads/173412-Skyshop-Image-Based-Lighting-Tools