Home Technical Talk

Bake HDR information in one RGB image

polycounter lvl 8
Offline / Send Message
Seenax polycounter lvl 8
Hello guys,

Download link: http://www.seenax.com/portfolio/cpp.php

I found a way to bake HDR information in one RGB image (without using any alpha channel)!!! This is a very useful technique for baking HDR lightmaps.

I used Y = 0.2126 R + 0.7152 G + 0.0722 B function to get luminance out of an image.

Lightmap encoding
LightmapPostProcess.jpg

In-shader computation to reverse the process
Lightmap_shader_uncode.jpg

I hope it's useful,
Gabriel

Replies

  • Eric Chadwick
    Hmm, I don't understand how it's HDR, and how it's a single image. Are you only using a single RGB, and is it the Base image? What does it look like at full-res? Almost seems like the highlights are all blown out, so you've lost resolution there.

    I've been baking psuedo-HDR lightmaps lately. I calculate the lighting in my scene, then swap all my materials at bake time with a 127 gray diffuse material, and bake a Complete Map in 3ds Max's Render To Texture, saving it as a standard 24bit TGA.

    This sets the lightmap so middle gray is my middle brightness value. Then in my shader I multiply this lightmap 2x, and multiply that with the original diffuse maps. This way I get overbrightening in-game. The result closely matches the original lighting as rendered in 3ds Max, but I get it in realtime 3d.
  • Seenax
    Offline / Send Message
    Seenax polycounter lvl 8
    I know the *2 technique, it's pretty old.
    Let's suppose Base is an HDR lightmap (with 32bits/channel) and you want to keep this information but you can't use an HDR image with 32bits/channel in game, can you? Now you can use an RGBM encoding(or anything similar), but it uses the alpha channel, and an image with alpha channel would end up having a pretty nasty compression. What I described above is a technique that uses no alpha channel but still holds most of the original HDR information.
  • Eric Chadwick
    Can you post a test texture encoded with this technique?
  • Seenax
  • Xoliul
    Offline / Send Message
    Xoliul polycounter lvl 14
    Where are you getting these weights from:
    0.2126 R + 0.7152 G + 0.0722 B

    I thought official grayscale weights were different?
  • radiancef0rge
    Offline / Send Message
    radiancef0rge ngon master
    Looks like an interesting technique although Im not sure the advantages over just using the alpha channel other than memory? We did this a lot on a recent title I worked on where we stored the HDR info for our skies into the Alpha

    What are you using to preview the shader code?
  • Seenax
    Offline / Send Message
    Seenax polycounter lvl 8
    @Xoliul: wiki http://en.wikipedia.org/wiki/Luminance_(relative)

    @radiancef0rge: Memory and compression. You need as much precision as you can get when it comes to HDR fake, and alpha textures are compressed pretty bad which means bad precision.
    Notepad++ for previewing shader code.
  • radiancef0rge
    Offline / Send Message
    radiancef0rge ngon master
    Notepad++ has a visualizer for shader code?
  • Ashaman73
    Offline / Send Message
    Ashaman73 polycounter lvl 6
    Any compression would do, even a capped linear compression. But the issue with it is, that you compress a very large range into 8 bits. The resolurion is really bad.

    Where is the disadvantage when using an additional channel for eg RGBM, or even half-float format for hdr ? You compression works only to reduce the demand on the harddisk, but on the videocard you still would utilize hardware supported compression and color spaces (dds format, srgb etc). Eg your compression on top of dxt5 would lead to really ugly artifacts (small changes in the source image would result in extrem changes in the final image).

    Consider this in combination with hardware compression (example 1024x1024):
    RGB (log10 compression) vs RGBM(DXT5 compression)
    ~3mbyte vs ~1mbyte

    And with RGBM you would have higher quality. If you compress RGB-log10 further by using eg DXT5, the quality reduction would be really hurting.

    PS: this kind of compression might be useful on old-gen hardware (PS/Xbox360) where you use it in combination with rendertargets to use hdr rendering ingame (32bit vs 64bit render targets), but this rendertargets are not hardware compressed any further (performance issues). But texture use hardware compression (you have a performance gain here !).
  • Seenax
    Offline / Send Message
    Seenax polycounter lvl 8
    @radiancef0rge: I use 3dsmax viewport, sry. Notepad++ for editing

    @Ashaman73: take a look at this:
    (the raw lightmap wasn't used in any test and it's here so you can compare the log10RGB encoded lightmaps with it)

    Render.jpg
    LightmapShowcase.jpg

    Decode the lightmap in shader and you get true HDR images:
    SceneTest.jpg
  • AlecMoody
    Offline / Send Message
    AlecMoody ngon master
    That 928 looks familiar.

    Edit:
    Can we see an example of this using actual HDR source content? Something like a spherical HDR pano so we can see how well it preserves both highlight and shadow detail at different exposure levels.
  • Eric Chadwick
    This looks great.

    How do you encode the lightmap?

    Can someone point me to an explanation of the alpha channel technique? I've heard in mentioned before but never dug into how it's done.
  • Seenax
    Offline / Send Message
    Seenax polycounter lvl 8
    @Eric: RGBM http://www.polycount.com/forum/showthread.php?t=121383

    But do keep in mind that RGBA textures have a pretty shitty compression on mobile(not to mention the worst of all which is on android (ETC compression)). This is why I prefer my method over RGBM or anything similar.
  • Seenax
  • Seenax
    Offline / Send Message
    Seenax polycounter lvl 8
    AlecMoody wrote: »
    That 928 look familiar.

    Hahahha, I didn't get it at first but I've just seen it on your website. I must have saved it on my PC because it is pretty damn cool. I hope you don't mind I overexposed it and used it for world domination purposes :)
  • Ashaman73
    Offline / Send Message
    Ashaman73 polycounter lvl 6
    I'm not familiar with mobile and mobile compression, so your approach could be absolutly legal on these devices.
    But you can see clear artifacts on the DXT4 compressed images. DXT compression has always artifacts, it is just a matter of things how your data hide these artifacts. Using a log10 compression will increase the visibility of these artifacts.

    On non-mobile GPUs (console/PC) you need to consider the following:

    1. You have atleast 4 channels, no GPU will save any space or bandwidth if only using 3 channels, therefor all GPUs will handle a RGB image internally as RGBA image. Forcing a GPU to do otherwise will at most result in a perfomance hit.

    2. If you have 4 channels, why not use the 4th one to hold additional data which will improve the quality of the other three channels ? This is the way RGBM/E works. You should use a comparision image between different HDR compression algorithm, not different hardware texture compression algorithms (compare dxt4 textures of log10, rgbe xyze etc.)

    The log10 compression reduced the bit resolution of colors. Some games even use the alpha channel to increase the color resolution (crisis ?), by expanding the value range of the RGB channels and save the according factor in the alpha channel. This way you have more than 8 bits color space on a standard 8-bit RGBA texture.

    It is just a matter of quality, but most games will try to get out the highest quality level for the loweset budget. And using GPU supported compression is not to save memory in the first place, but memory bandwidth, which has a heavy impact on performance.
  • Seenax
    Offline / Send Message
    Seenax polycounter lvl 8
    Log10RGB might not save performance but it saves memory. Download these 2 images:

    http://seenax.com/images/DXT1_log10RGB.dds
    http://seenax.com/images/DXT5_log10RGB.dds

    You will notice that DXT1 has 512KB unlike DXT5 which has 1024KB, but the RGB channels are absolutely IDENTICAL. The only difference is that DXT1 has no alpha channel unlike DXT5. These being said log10RGB uses twice as less memory and the quality loss compared to RGBM(if any) is quite minimal.

    To make use of all 0-1 range you can calculate a constant (K) that multiplied with the RGB image = logRGB image, like this:

    K = 0.541176
    QualitySave.jpg

    With this constant the in-shader decoding should use 10^(FR_lum*K) - 1 instead of 10^FR_lum - 1
  • Seenax
    Offline / Send Message
    Seenax polycounter lvl 8
    log10RGB(512kb) vs RGBM(1024kb), same res.

    log10RGB info:
    If your brightest bixel in your HDR image is >= 10 then K is 1.0 since log10 (10) = 1. (which means you already used all 0-1 interval). In this case the first image is the worst case scenario.

    log10_vs_RGBM.jpg
  • Ashaman73
    Offline / Send Message
    Ashaman73 polycounter lvl 6
    Seenax wrote: »
    Log10RGB might not save performance but it saves memory.
    ...
    You will notice that DXT1 has 512KB unlike DXT5 which has 1024KB, but the RGB channels are absolutely IDENTICAL.
    Well, this is a valid point, because saving GPU memory is a big performance improver (bandwidth is one of the most, if not the top, performance killer in modern render pipelines, though this might not be so relevant to low-access textures, eg background textures).

    The options on quality differs and eventually it will be the decision of the artist and some real world scenerios to choose a suitable solution.
  • Seenax
    Offline / Send Message
    Seenax polycounter lvl 8
    I've made a mini software that encodes HDRs using known methods. You can download it from http://www.seenax.com/portfolio/cpp.php
Sign In or Register to comment.