Hello there!
I have found a few other issues related to sRGB, but they simply do not help me and I am still incredibly confused. My problem is that ContextBuilder::with_srgb
does not seem to have any effect. Check out this minimal example (using glium
):
#[macro_use]
extern crate glium;
fn main() {
#[allow(unused_imports)]
use glium::{glutin, Surface};
let events_loop = glutin::EventsLoop::new();
let wb = glutin::WindowBuilder::new();
let cb = glutin::ContextBuilder::new().with_srgb(false); // MARK A -------
let display = glium::Display::new(wb, cb, &events_loop).unwrap();
#[derive(Copy, Clone)]
struct Vertex {
position: [f32; 2],
}
implement_vertex!(Vertex, position);
let shape = vec![
Vertex { position: [-1.0, -1.0] },
Vertex { position: [-1.0, 1.0] },
Vertex { position: [ 1.0, -1.0] },
Vertex { position: [ 1.0, 1.0] },
];
let vertex_buffer = glium::VertexBuffer::new(&display, &shape).unwrap();
let indices = glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip);
let vertex_shader_src = r#"
#version 140
in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
"#;
let fragment_shader_src = r#"
#version 140
out vec4 color;
void main() {
color = vec4(vec3(0.5), 1.0);
}
"#;
let program = glium::Program::new(
&display,
glium::program::ProgramCreationInput::SourceCode {
vertex_shader: vertex_shader_src,
tessellation_control_shader: None,
tessellation_evaluation_shader: None,
geometry_shader: None,
fragment_shader: fragment_shader_src,
transform_feedback_varyings: None,
outputs_srgb: false, // MARK B ----------------------------------
uses_point_size: false,
}
).unwrap();
loop {
let mut target = display.draw();
target.draw(&vertex_buffer, &indices, &program, &uniform!{}, &Default::default()).unwrap();
target.finish().unwrap();
}
}
There are two places of interest which I will explain later.
.with_srgb(_) // MARK A
outputs_srgb: _, // MARK B
My test setup is the following: I run this program and take a screenshot and then inspect what color value the pixels have. For the four possible configurations, I get the following values:
| | .with_srgb(false)
| .with_srgb(true)
|
| - | - | - |
| outputs_srgb: false
| #bbbbbb
| #bbbbbb
|
| outputs_srgb: true
| #808080
| #808080
|
So as far as I understand: there is the GL_FRAMEBUFFER_SRGB
flag. If that flag is false
, OpenGL does not perform any conversion from fragment shader to frame buffer. If it is enabled, however, OpenGL assumes that the shader output is linear RGB and will thus -- if the frame buffer has an sRGB format -- convert the shader output to sRGB. In glium
, GL_FRAMEBUFFER_SRGB
is controlled by the outputs_srgb
parameter of the program. If the latter is false
, GL_FRAMEBUFFER_SRGB
is set to true
and the other way around.
Additionally, I would expect glutin
to create a framebuffer with the format specified by .with_srgb(_)
. As such, I have the following expectations:
- ✗
with_srgb(false)
and outputs_srgb: false
: the framebuffer should be linear RGB, meaning that no conversion should happen, regardless of GL_FRAMEBUFFER_SRGB
. As such, I would expect #808080
, but I got #bbbbbb
.
- ✔
with_srgb(true)
and outputs_srgb: false
: the framebuffer should be sRGB and since the shader does not output sRGB, I expect OpenGL to convert. As such, I expect #bbbbbb
, which I actually got.
- ✔
with_srgb(false)
and outputs_srgb: true
: as above, the framebuffer should be linear RGB, meaning that no conversion should happen, regardless of GL_FRAMEBUFFER_SRGB
. As such, I would expect #808080
which I luckily also got.
- ✔
with_srgb(true)
and outputs_srgb: true
: the framebuffer is sRGB, but the shader also outputs in that color space, so no conversion should happen. As such I expect #808080
which I got.
This issue is about the first situation. As far as I can tell, this is just wrong.
I tested the above on several platforms: Ubuntu 18.04, MacOS and Windows. I always got the same results (well, on MacOS and Windows the #bbbbbb
was slightly off, but still way more than #808080
).
(I also did a test with GLFW in case that's interesting. I used the simple
example and changed line 63 to " gl_FragColor = vec4(vec3(0.5), 1.0);\n"
. Running that, I get a #808080
triangle.)
Am I doing something wrong? Am I completely misunderstanding color spaces? Is this a bug in glutin
/glium
/...? Would be super great if someone could help me!