Closed michidk closed 3 years ago
Hello Michael,
thanks for this awesome tutorial! It was a great help getting into Vulkan/Ask.
I'm glad to hear that!
And there we only select the first one. Why is that? Is the order always guaranteed to be the same? Then why just don't we specify
VK::Format::B8G8R8A8_UNORM
directly?
Due to laziness and this being "stumbling around and figuring things out" code. Picking the "most suitable one" instead of "just the first" would be very reasonable. (At least, taking the first one makes sure that it really is valid...)
I don't think there is a guarantee for the order, and would expect the order to change if I switched GPU or graphics driver etc. (On the other hand, I don't expect it to change from one run of the program to the next, but this is an assumption that is probably not backed by any guarantee on the part of Vulkan.)
Also, I was under the impression, that only
B8G8R8A8_SRGB
applies the gamma correction automatically? But I can't find any other part of the application, which might influence the SRGB/linear/gamma space behaviour. In fact when specifying the B8G8R8A8_SRGB format instead of the UNORM one, the picture still looks exactly the same?
I think the important part here is the second part of the SurfaceFormat:
color_space: SRGB_NONLINEAR
should entail the nonlinear (that is, approximately, the gamma corrected) interpretation.
Possibly relevant links: https://stackoverflow.com/questions/65241749/what-is-vulkan-color-space https://old.reddit.com/r/vulkan/comments/4v3y74
Hi Hoj-senna, thank you for your fast reply!
I don't think there is a guarantee for the order and would expect the order to change if I switched GPU or graphics driver etc. (On the other hand, I don't expect it to change from one run of the program to the next, but this is an assumption that is probably not backed by any guarantee on the part of Vulkan.)
That's a very good point. A good idea would probably be to have an array of VK::Format, with formats that might work and then look if one of them is supported and pick that one. Or just assume one and panic otherwise.
I think the important part here is the second part of the SurfaceFormat [...]
I thought that too. But then it is so weird, that my GTX 1080 only supports SRGB_NONLINEAR? (As you can see in the debug output from my first post: there is no other color space than SRGB_NONLINEAR
). But it's also weird that I only get three supported formats, so maybe something else is wrong, too.
Anyway, thanks for your explanation!
I think the important part here is the second part of the SurfaceFormat [...]
I thought that too. But then it is so weird, that my GTX 1080 only supports SRGB_NONLINEAR? (As you can see in the debug output from my first post: there is no other color space than
SRGB_NONLINEAR
). But it's also weird that I only get three supported formats, so maybe something else is wrong, too.
I don't think it's that weird. After all, this is only about colour spaces for the "final output", and other possible colour spaces in https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap34.html#VkColorSpaceKHR are "stranger".
That you can use different colour formats for vkImage
s should not be affected by these surface capabilities. No need for something to be wrong.
That makes sense! Again - thank you a lot!
Hmm.. but still.
I think we shoud use B8G8R8A8_SRGB
or apply the gamma correction in the shader as a last step.
I guess color_space: SRGB_NONLINEAR
just means that the surface/buffer expects the output to be in SRGB.
Thank you for your insistence.
After some additional reading my current understanding is the following.
(And now that I've written it, I see your edit. The final conclusion seems to be the same: I should have used SRGBA instead of UNORM in all places.)
The different places of "format":
There is the final step: Bytes are given to the "surface", are "presented". Question: What colour does "red=128", "red=10", "red=0" or "red=255" stand for? Answer: Interpret it as an sRGB value. (Or rather: interpret it according to the "image_color_space" set during swapchain creation.) This is the color_space we were talking about.
Then there is the "format" of swapchain and other images: It might be related to how values in memory are supposed to be treated, but actually is mainly responsible for the decision how many bytes are used for each fragment's colour (i.e. if there is some compression etc.), but several formats are compatible with each other (the distinction between _UNORM and _SRGBA does not matter here).
When we (and not the surface/presentation) are working with them, the interpretation of bytes as data is regulated by the format specified for the ImageView.
When in the shader, we always deal with numbers between 0.0 and 1.0. But when we write these values to memory (via some ImageView), a decision has to be made: What value of the bytes to use. Here, sRGB is simply an encoding with more precision around 0.0 and less around 1.0 (which is in accordance with human perception and, if I've read that correctly, with most picture files). In contrast to this, for UNORM all possible values are evenly spaced. (Using UNORM makes more sense when the values are not colours.)
So, when we say that an ImageView is UNORM, when we write to it, and later present it with a color_space of SRGBA, this reinterpretation is an additional gamma correction.
Always using SRGBA means that there are no unintended reinterpretations of the values.
(This also means I should change quite some places in my code. — Inside the shader, for numbers between 0.0 and 1.0 it makes no difference; and whenever the input is read from some texture from a file, it probably already was sRGB encoded. The remaining place is the discrepancy between writing the colour and reading it for presentation, which we want to fix.)
If you are used to having to do gamma corrections by hand, you probably view the step "values in [0.0,1.0] are stored in an sRGB encoding" as a gamma correction. If you are not used to this correction being an additional necessary step, this is merely a particularity of the encoding that one can completely ignore.
If you want to get rid of a "gamma correction that is automatically applied", you can always take "value to the power 2.2" and thus revert "value to the power 1/2.2" or vice versa (and one of these should approximately coincide with the gamma correction).
edit to clarify: This point was a bit too hidden in my summary: Whenever I talk about "values between 0.0 and 1.0" (i.e. the values in the shader), they always are to be understood as intensities and similar quantities (and thus "in linear space").
Yeah sorry. In fact I had to edit it multiple times, because I was so confused by this hole color space theme. Great summarization. In fact in the shader, we have to use linear space (which looks wrong to our eyes), otherwise, our BRDF calculations would be wrong (multiplying color or light values would yield other values than in the gamma-corrected space).
Hello,
thanks for this awesome tutorial! It was a great help getting into Vulkan/Ask.
I just have one question. Normally when working with OpenGL, one has to convert the colors to gamma space at the end of the shader to make the color brightness look more real:
pow(radiance.xyz, vec3(1.0/2.2));
.But you didn't apply the gamma correction. Also, when rendering all brightness levels, it seems to look correct. Applying gamma just makes it way too bright. So it seems like the image is already gamma-corrected.
Without gamma correction:
With gamma correction:
So I found out, that we create the framebuffer with the format from
surfaces.get_formats(physical_device)
, which in my case returns the following:And there we only select the first one. Why is that? Is the order always guaranteed to be the same? Then why just don't we specify
VK::Format::B8G8R8A8_UNORM
directly? Also, I was under the impression, that onlyB8G8R8A8_SRGB
applies the gamma correction automatically? But I can't find any other part of the application, which might influence the SRGB/linear/gamma space behaviour. In fact when specifying the B8G8R8A8_SRGB format instead of the UNORM one, the picture still looks exactly the same?Thanks, Michael