I am working on a 3D engine as a hobby (Direct3D 11). Currently I am trying to implement sRGB -> linear -> sRGB color space conversions via texture formats with "_SRGB" suffix. So, my textures are supposed to be sRGB images (for example, DDS-files compressed in BC1_UNORM_SRGB format), output is also gamma-corrected (thanks to R8G8B8A8_UNORM_SRGB frame buffer) and all shader calculations are made in linear color space.

The problem is, whether I use sRGB or non-sRGB format for the DDS-file, after sampling the texture I get exactly the same color values inside the shader that are stored in original image. But if I get it correctly, sampler should apply implicit gamma correction (pow(color, 2.2f)) for the input values. So, for example, if I want to output the same color as is in the map (lets say, 0.5f for R channel), I sample it from the texture (0.5f becomes 0.218f after transferring to linear color space by sampler), then I do nothing with it inside the shader and send to output. As the frame buffer has sRGB format, merger (or some other part of pipeline, that does it) will apply gamma re-correction to our value (pow(color, 1.0f / 2.2f)), and 0.218f will become 0.5f again. I will get the same image as I had on the input.

The output colors are definitely gamma corrected, as I see clear difference when I change frame buffer format from sRGB to non-sRGB. But as no input correction is applied, the final image looks brightened comparing to the input one. As I said, I checked the value in pixel shader after texture.Sample() call, and it is exactly the same as colorpicker shows for the source texture. When I swap the texture format to non-sRGB, nothing changes (I use Visual Studio 2013 Update 4 for format changing).

To load DDS files I use DDSTextureLoader. I also called Direct3D methods directly to create resource and view from the file, but nothing changed. Both resource and shader resource view have "_SRGB" format, as I can see in Graphics Debugger, so they are definitely sRGB ones.

I've read at MSDN that in Direct3D 11 setting texture format is enough for sampler to recognize sRGB image. Is there something I am doing wrong or missing, or understand incorrectly? Maybe someone had similar issues? Any advice would be highly appreciated!


I'm not using DDSTextureLoader() functions myself, but it seems that the function creates appropriate shader resource view for you to match the DDS format and the associated sRGB space, thus you get about the same linearized result in the shader regardless if you use sRGB format in your DDS file or not. You could create your own SRV instead with fixed sRGB setting and use that to see the difference.

Just to clarify, you DO get sRGB-to-linear correction at sampling. If you store texture in linear space and use linear sampler you get the same result as storing the texture in sRGB space and using sRGB sampling (barring the precision differences).

| improve this answer | |
  • \$\begingroup\$ What exactly do you mean by "create your own SRV with fixed sRGB"? As far as I can tell, there are not so many parameters in SRV DESC structure. The only one that seems relevant to sRGB is format, which I set equal to the format of the resource (with "_SRGB" suffix). \$\endgroup\$ – WinterDog Oct 15 '14 at 16:57
  • \$\begingroup\$ Use sRGB format in the SRV description regardless of the format used in DDS. This is obviously wrong, but you should be able to see the expected change. The behaviour you get (i.e. nothing changes) is what you should get because both formats are linearized correctly by the sampler. Or do you want to get colors in sRGB space in the shader? \$\endgroup\$ – JarkkoL Oct 15 '14 at 20:06
  • \$\begingroup\$ Thanks for help so far! I set file format to BC1_UNORM and resource/SRV format to "_SRGB" in the code, and now it works as I wanted (e.g. texture's 0.5f -> 0.22f in PS -> 0.5f in output). But forgive me my ignorance, I still don't understand, why it happens. For example, here are recommendations to use sRGB formats for textures and frame buffer: http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html What's the purpose of DDS "_SRGB" formats then? Shader obviously needs data in linear space. "_SRGB" lets it know that input data is in sRGB space. Why isn't it changed in my initial example? \$\endgroup\$ – WinterDog Oct 15 '14 at 23:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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