<p>I have a project, in which my renderer can work standalone or render into an outside window.
When rendering to an outside window, the outside window uses Vulkan for rendering setup, but it really just passes data from my renderer through and does a bit of synchronization.</p>
<p>The actual renderer is using OpenGL and in standalone works fine.
When rendering to the outside window however, the linear-&gt;sRGB conversion via <code>glEnable(GL_FRAMEBUFFER_SRGB)</code> does not work (correctly).</p>
<p>About the setup for standalone:
Nothing fancy, just render a buffer (i.e. an image) to the default Framebuffer using GLFW. <code>glEnable(GL_FRAMEBUFFER_SRGB)</code> works as expected.</p>
<p>About the setup for rendering to outside window:
A <code>VkImage</code> is created on the outside in Vulkan and imported in OpenGL as memory with a memory ojbect and an OpenGL texture based on that memory. An FBO is created and the OpenGL texture based on imported memory used as the render target.
Import is done with <code>glImportMemoryWin32HandleEXT</code> and <code>glTextureStorageMem2DEXT(id, miplevels, format, width, height, memObj, 0)</code>.</p>
<p>The format determines if the <code>FRAMEBUFFER_SRGB</code> state has effect, so using <code>VK_FORMAT_R32G32B32A32_SFLOAT</code> and <code>GL_RGBA32F</code> means no effect (as expected, this &quot;works&quot;).
However, since I want to have the conversion and the Vulkan side does nothing, I tried the following:
On Vulkan side, choose <code>VK_FORMAT_R8G8B8A8_UNORM</code> such that the data is interpreted as linear and not converted in shader reads or writes, or in presentation. On OpenGL side choose `GL_RGBA8_SNORM´ such that it is interpreted as sRGB for write operations (i.e. in draw calls) and conversion happens.</p>
<p>However, using this the image actually gets darker instead of brighter, so it looks like instead of getting converted linear-&gt;sRGB it actually does sRGB-&gt;linear somewhere.</p>
<p>Now I am a bit at a loss as to why that is (and therefore how to fix it). From the way I understand it, <code>GL_FRAMEBUFFER_SRGB</code> should do sRGB-&gt;linear for reads and linear-&gt;sRGB for writes. I only write to the image via FBO. The state is not changed for any other reads or writes, i.e. the draw call is pretty much</p>
<pre><code>glEnable(GL_FRAMEBUFFER_SRGB);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisable(GL_FRAMEBUFFER_SRGB);
</code></pre>
<p>And the shader has a texture bound that is using <code>glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr)</code> (this is the image is created in the actual renderer, so not the one imported from Vulkan), so no conversion should happen there when reading.</p>
<p>For debugging I tried to use <code>GL_RGBA8</code> on OpenGL side on the imported <code>VkImage</code>, and then the result is the same as with the the 32bit float format - no conversion happens at all.</p>

CC BY-SA 4.0
2024-12-01T12:05:49.283Z
For Vulkan to display to a window surface it typically needs a surface format. What is the VkSurfaceFormat being used?
pmw1234
CC BY-SA 4.0
2024-12-02T10:35:13.430Z
The swapchain is created with format `VK_FORMAT_B8G8R8A8_UNORM`.The window is a Qt one and I can't create the swapchain myself - not sure if I can select the surface format. Either way, I'd like to keep the conversion out of Vulkan and this one shouldn't add a conversion.
Tare
<colorspace><interop>
Why does writing to FBO with GL_FRAMEBUFFER_SRGB darken the image
Tare
# Why does writing to FBO with GL_FRAMEBUFFER_SRGB darken the image

(Asked by: username_0 on 2024-12-01)

I have a project, in which my renderer can work standalone or render into an outside window.
When rendering to an outside window, the outside window uses Vulkan for rendering setup, but it really just passes data from my renderer through and does a bit of synchronization.

The actual renderer is using OpenGL and in standalone works fine.
When rendering to the outside window however, the linear->sRGB conversion via `glEnable(GL_FRAMEBUFFER_SRGB)` does not work (correctly).

About the setup for standalone:
Nothing fancy, just render a buffer (i.e. an image) to the default Framebuffer using GLFW. `glEnable(GL_FRAMEBUFFER_SRGB)` works as expected.

About the setup for rendering to outside window:
A `VkImage` is created on the outside in Vulkan and imported in OpenGL as memory with a memory ojbect and an OpenGL texture based on that memory. An FBO is created and the OpenGL texture based on imported memory used as the render target.
Import is done with `glImportMemoryWin32HandleEXT` and `glTextureStorageMem2DEXT(id, miplevels, format, width, height, memObj, 0)`.

The format determines if the `FRAMEBUFFER_SRGB` state has effect, so using `VK_FORMAT_R32G32B32A32_SFLOAT` and `GL_RGBA32F` means no effect (as expected, this "works").
However, since I want to have the conversion and the Vulkan side does nothing, I tried the following:
On Vulkan side, choose `VK_FORMAT_R8G8B8A8_UNORM` such that the data is interpreted as linear and not converted in shader reads or writes, or in presentation. On OpenGL side choose `GL\_RGBA8\_SNORM´ such that it is interpreted as sRGB for write operations (i.e. in draw calls) and conversion happens.

However, using this the image actually gets darker instead of brighter, so it looks like instead of getting converted linear->sRGB it actually does sRGB->linear somewhere.

Now I am a bit at a loss as to why that is (and therefore how to fix it). From the way I understand it, `GL_FRAMEBUFFER_SRGB` should do sRGB->linear for reads and linear->sRGB for writes. I only write to the image via FBO. The state is not changed for any other reads or writes, i.e. the draw call is pretty much

```
glEnable(GL_FRAMEBUFFER_SRGB);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisable(GL_FRAMEBUFFER_SRGB);

```

And the shader has a texture bound that is using `glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr)` (this is the image is created in the actual renderer, so not the one imported from Vulkan), so no conversion should happen there when reading.

For debugging I tried to use `GL_RGBA8` on OpenGL side on the imported `VkImage`, and then the result is the same as with the the 32bit float format - no conversion happens at all.

**Tags:** colorspace, interop

> **Comments:**
> **username_1**: For Vulkan to display to a window surface it typically needs a surface format. What is the VkSurfaceFormat being used?  
> **username_0**: The swapchain is created with format `VK_FORMAT_B8G8R8A8_UNORM`.The window is a Qt one and I can't create the swapchain myself - not sure if I can select the surface format. Either way, I'd like to keep the conversion out of Vulkan and this one shouldn't add a conversion.  

---

## 0 answers

