Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am writing a game using SharpDX with DirectX11 and I have been reading that it is important to apply gamma correction to my engine in order to perform correct linear lighting calculations.

So I modified the function which loads my diffuse texture maps so that it uses R8G8B8A8_UNorm_SRgb format rather than R8G8B8A8_UNorm. I then modified my framebuffer format so that it also uses R8G8B8A8_UNorm_SRgb.

It was my understanding that this would use hardware to remove gamma correction from my textures allowing me to perform linear lighting calculations and then reapply gamma correction when rendering the final scene to the frame buffer.

However when I do this the scene looks washed out and too bright. My next step was to take a look at some gamma calibration charts Gamma Calibration Chart. When viewing this chart in my browser I get a value of approximately 2.2.

I then loaded this chart into my engine and rendered it to screen. When using R8G8B8A8_UNorm I get the same value (approximately 2.2) but when using R8G8B8A8_UNorm_SRgb I get a value around 1.2.

It seems like the scene has already been gamma corrected somehow. Is this the case, what am I missing?

share|improve this question
    
Do you have any lighting in your scene? If you do, the light colors likely need to be converted to linear space as well. A useful test is to temporarily disable lighting and just render the textures directly to the framebuffer without doing any math on them. They should appear the same with or without the _SRGB formats, since the gamma correction is being done and then undone. –  Nathan Reed May 30 '13 at 21:42
    
It's also worth noting that the gamma calibration chart cannot be filtered at all or it's likely to be completely screwed up, so ensure you're viewing it with nearest-neighbor sampling in your engine. –  Nathan Reed May 30 '13 at 21:51
    
The lighting is not applied to the gamma chart and I am sampling using MinMagMipPoint with min/max 0 mip lod. Also, the chart appears correctly for non-sRGB format. –  gareththegeek May 30 '13 at 21:57
1  
Current hardware should implement srgb conversion before doing texture filtering and thus should not have any problems with texture filtering. It sounds like the sRGB framebuffer works fine but texture filtering does not do the sRGB conversion. Does not using sRGB for the diffuse texture have any changes on the output? Does applying pow(sample, 2.2) in shader instead of using the sRGB format result in a similar output? –  Archy May 31 '13 at 0:25
    
@Archy - you were correct, I was not removing gamma correction from my textures - see my answer below. –  gareththegeek May 31 '13 at 15:42

1 Answer 1

up vote 1 down vote accepted

As suggested by Archy, sRGB conversion was not being applied to my texture maps.

The problem was that I missed a flag from the ImageLoadInformation used to load my diffuse texture maps. This meant that gamma correction was not being removed from my source textures before lighting was applied, leading to double gamma correction on output to the frame buffer.

return (Texture2D)Texture2D.FromFile(
    DeviceManager.Instance.Device,
    filename,
    new ImageLoadInformation
    {
        Format = Format.R8G8B8A8_UNorm_SRgb,
        Filter = FilterFlags.SRgbIn | FilterFlags.None,
        BindFlags = BindFlags.ShaderResource,
        CpuAccessFlags = CpuAccessFlags.None,
        Usage = ResourceUsage.Default
    });

I was missing

Filter = FilterFlags.SRgbIn
share|improve this answer
    
Good you got it working, but I think your explanation might be backwards - if I understand correctly, FilterFlags.SRgbIn causes the texture loader to assume the texture is already in sRGB format. Without it, it was probably assuming the texture was linear and converting to sRGB on load; then the texture sampler in the shader would undo that conversion, giving you the original texture data (sRGB) in the shader, where linear data was desired. –  Nathan Reed May 31 '13 at 16:23
    
I am more confused now than ever! So do I want to use sRGB format and FilterFlags.None? On a related note, I am now suffering from serious quantization in dark colours, there are bands of colour to do with the way that rgb colour is corrected on output. –  gareththegeek Jun 1 '13 at 16:54
    
You want to use sRGB format, and whatever flag combination causes the texture loader to leave your texture well enough alone when loading it. I'm not an expert on SharpDX so you'll need to consult the docs (and maybe run some experiments) to determine this. –  Nathan Reed Jun 1 '13 at 18:56
1  
And the quantization in the dark colors is probably a sign of something being converted from sRGB to linear and then stored in an RGBA8 texture or buffer, then converted back to sRGB at some point. Linear color space requires more than 8 bits of precision (which is one reason why we store textures in sRGB space to begin with). –  Nathan Reed Jun 1 '13 at 18:58
    
Ahh of course, so I need to upgrade my deferred shader's gbuffer to greater precision if I want to work in linear colour space. I was considering looking at HDR lighting next anyway so moving to R16G16B16A16_FLOAT is probably to only way forward. Thanks for your help! –  gareththegeek Jun 1 '13 at 19:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.