New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add outputs_srgb example (Showing difference between sRGB and linear RGB) #2098
base: master
Are you sure you want to change the base?
Conversation
Jason's compilation comprises the context, but #2059 per se is a sufficient summary. The This is certainly easier to explain with a visualization, but the comments at the top of the file may be a bit confused. EDIT: diffdiff --git a/examples/srgb_shader.rs b/examples/srgb_shader.rs
index cd42171..a2587ae 100644
--- a/examples/srgb_shader.rs
+++ b/examples/srgb_shader.rs
@@ -69,6 +69,8 @@ struct Application {
pub vertex_buffer: glium::VertexBuffer<Vertex>,
pub linear_rgb_program: glium::Program,
pub srgb_program: glium::Program,
+ pub texture_2d: glium::Texture2d,
+ pub srgb_texture_2d: glium::texture::SrgbTexture2d,
}
impl ApplicationContext for Application {
@@ -92,16 +94,19 @@ impl ApplicationContext for Application {
}
let vertex_buffer = { glium::VertexBuffer::new(display, &vertices).unwrap() };
+ let texture_2d = glium::Texture2d::empty(display, 800, 600).unwrap();
+ let srgb_texture_2d = glium::texture::SrgbTexture2d::empty(display, 800, 600).unwrap();
+
Self {
vertex_buffer,
linear_rgb_program: create_program(display, false),
srgb_program: create_program(display, true),
+ texture_2d,
+ srgb_texture_2d,
}
}
fn draw_frame(&mut self, display: &Display<WindowSurface>) {
- let mut frame = display.draw();
-
// Draw band of linear RGB gradient at the top of the window
let linear_rgb_uniforms = uniform! {
matrix: [
@@ -121,27 +126,107 @@ impl ApplicationContext for Application {
]
};
- // Clear the window with some non-grey color, to make the gradients stand out a bit
- frame.clear_color(0.1, 0.3, 0.1, 1.0);
-
- frame
- .draw(
- &self.vertex_buffer,
- NoIndices(PrimitiveType::TriangleStrip),
- &self.linear_rgb_program,
- &linear_rgb_uniforms,
- &Default::default(),
- )
- .unwrap();
- frame
- .draw(
- &self.vertex_buffer,
- NoIndices(PrimitiveType::TriangleStrip),
- &self.srgb_program,
- &srgb_uniforms,
- &Default::default(),
- )
- .unwrap();
+ // Draw the gradient with each program on a non-sRGB texture
+ let mut framebuffer_linear = glium::framebuffer::SimpleFrameBuffer::new(
+ display,
+ &self.texture_2d
+ )
+ .unwrap();
+ framebuffer_linear.clear(None, Some((0.1, 0.3, 0.1, 1.0)), false, None, None); // clear_color
+ framebuffer_linear.draw(
+ &self.vertex_buffer,
+ NoIndices(PrimitiveType::TriangleStrip),
+ &self.linear_rgb_program,
+ &linear_rgb_uniforms,
+ &Default::default(),
+ )
+ .unwrap();
+ framebuffer_linear.draw(
+ &self.vertex_buffer,
+ NoIndices(PrimitiveType::TriangleStrip),
+ &self.srgb_program,
+ &srgb_uniforms,
+ &Default::default(),
+ )
+ .unwrap();
+ let mut framebuffer_srgb = glium::framebuffer::SimpleFrameBuffer::new(
+ display,
+ &self.srgb_texture_2d
+ )
+ .unwrap();
+ // Draw the gradients again on an sRGB texture
+ framebuffer_srgb.clear(None, Some((0.1, 0.3, 0.1, 1.0)), true, None, None); // clear_color_srgb
+ framebuffer_srgb.draw(
+ &self.vertex_buffer,
+ NoIndices(PrimitiveType::TriangleStrip),
+ &self.linear_rgb_program,
+ &linear_rgb_uniforms,
+ &Default::default(),
+ )
+ .unwrap();
+ framebuffer_srgb.draw(
+ &self.vertex_buffer,
+ NoIndices(PrimitiveType::TriangleStrip),
+ &self.srgb_program,
+ &srgb_uniforms,
+ &Default::default(),
+ )
+ .unwrap();
+
+ // Blit both textures twice, toggling color correction
+ let mut frame = display.draw();
+ frame.clear(None, None, false, None, None);
+ let rect = glium::Rect {
+ left: 0,
+ bottom: 0,
+ width: 800,
+ height: 600,
+ };
+ frame.blit_from_simple_framebuffer(
+ &framebuffer_linear,
+ &rect,
+ &glium::BlitTarget {
+ left: 0,
+ bottom: 0,
+ width: 400,
+ height: 300,
+ },
+ glium::uniforms::MagnifySamplerFilter::Linear,
+ );
+ frame.blit_from_simple_framebuffer(
+ &framebuffer_srgb,
+ &rect,
+ &glium::BlitTarget {
+ left: 400,
+ bottom: 0,
+ width: 400,
+ height: 300,
+ },
+ glium::uniforms::MagnifySamplerFilter::Linear,
+ );
+ frame.clear(None, None, true, None, None);
+ frame.blit_from_simple_framebuffer(
+ &framebuffer_linear,
+ &rect,
+ &glium::BlitTarget {
+ left: 0,
+ bottom: 300,
+ width: 400,
+ height: 300,
+ },
+ glium::uniforms::MagnifySamplerFilter::Linear,
+ );
+ frame.blit_from_simple_framebuffer(
+ &framebuffer_srgb,
+ &rect,
+ &glium::BlitTarget {
+ left: 400,
+ bottom: 300,
+ width: 400,
+ height: 300,
+ },
+ glium::uniforms::MagnifySamplerFilter::Linear,
+ );
frame.finish().unwrap();
}
} |
But I don't know that part of OpenGL and was hoping I could learn it through the way I'm consuming it ( I'm open to suggestions how to better word the description for the example! Or other ways of implementing it that makes it easier to understand.
This was not really obvious to me. And the documentation for The best would of course be to be able to visualize the pipelines how color values travel from wherever they start to the actual physical monitor. Where gamma correction is added/reversed and what more steps there are. Personally I don't care too much about textures. I have color values in XYZ-format that I get from various colorimetry tools. And I want to write software that renders these values as correct as possible (I'm aware that anything outside the sRGB gamut won't be possible to display of course). |
@justincredible Do you have the source code for your four examples available? When you say you enable and disable color correction, what are you referring to exactly? |
There is a git-diff below the image, but I've also provided the altered source here. There is another level to explore with how the background is cleared for both types of textures. The I'm relatively new to this library and the practicalities of sRGB, so I may be ignorant of some wider context. |
Aaah. I did not find those. If you search for
Those docs must surely be outdated, no? Because they say:
While the |
For my own understanding, what's the correct/simplest way to just render linear RGB values directly to the window framebuffer? I don't have any textures. I just have linear RGB data that I want to render as simple but correct as possible. I can encode them to srgb also, but if I can avoid that step and have OpenGL do whatever color correction is needed that's just simpler. My understanding is that I should then do |
|
Given that my shader writes srgb values, no? What if my shader writes linear rgb to the display framebuffer? Edit: is the display framebuffer always linear, never an srgb target? EDIT2: No, they differ. The display framebuffers I get when using glium via the gtk4 crate are not sRGB images, but the targets set up by the examples in this repository are sRGB images. So in my gtk4 program it does not matter what I set anything to, no color correction is applied. |
I have been struggling a bit with rendering correct colors lately. As part of investigating this, I wanted to get a better understanding of what color spaces the shaders were expected to output. It was not intuitive to me how to change the sRGB configuration in glium, and there are not really any docs around it that I could find. All I found was #2069, talking about making it more intuitive. But that issue/PR did not add any docs or examples. It basically just changed the default value.
So I decided to create an example to show to myself how to do it and what difference it makes (gamma in this case). Figured I cold provide it upstream with these two intended outcomes:
Ping @jasoneveleth and @justincredible, You might be interested in this since you worked on the previous sRGB issue/PR.