mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-12 14:08:37 +00:00
Handle sRGB colours properly
This commit is contained in:
parent
0cafc5c22d
commit
84020a6bc0
@ -20,6 +20,8 @@ fn main() {
|
||||
|
||||
// OpenGL context from glow
|
||||
let gl = glow_context(&window);
|
||||
// Outputting to screen, we want an sRGB framebuffer
|
||||
unsafe { gl.enable(glow::FRAMEBUFFER_SRGB) };
|
||||
|
||||
// OpenGL renderer from this crate
|
||||
let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context)
|
||||
|
||||
@ -12,7 +12,7 @@ use utils::Triangler;
|
||||
|
||||
fn main() {
|
||||
let (event_loop, window) = utils::create_window(
|
||||
"Hello, triangle!",
|
||||
"Hello, triangle! (GLES 3.0)",
|
||||
glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0)),
|
||||
);
|
||||
let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window);
|
||||
@ -23,7 +23,10 @@ fn main() {
|
||||
imgui_glow_renderer::Renderer::initialize(&gl, &mut imgui_context, &mut texture_map)
|
||||
.expect("failed to create renderer");
|
||||
// Note the shader header now needs a precision specifier
|
||||
let tri_renderer = Triangler::new(&gl, "#version 300 es\nprecision mediump float;");
|
||||
let tri_renderer = Triangler::new(
|
||||
&gl,
|
||||
"#version 300 es\nprecision mediump float;\n#define IS_GLES",
|
||||
);
|
||||
|
||||
let mut last_frame = Instant::now();
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
|
||||
@ -262,7 +262,7 @@ impl Lenna {
|
||||
gl.tex_image_2d(
|
||||
glow::TEXTURE_2D,
|
||||
0,
|
||||
glow::RGB as _,
|
||||
glow::SRGB as _,
|
||||
width as _,
|
||||
height as _,
|
||||
0,
|
||||
|
||||
@ -23,7 +23,11 @@ pub fn create_window(title: &str, gl_request: GlRequest) -> (EventLoop<()>, Wind
|
||||
}
|
||||
|
||||
pub fn glow_context(window: &Window) -> glow::Context {
|
||||
unsafe { glow::Context::from_loader_function(|s| window.get_proc_address(s).cast()) }
|
||||
unsafe {
|
||||
let gl = glow::Context::from_loader_function(|s| window.get_proc_address(s).cast());
|
||||
gl.enable(glow::FRAMEBUFFER_SRGB);
|
||||
gl
|
||||
}
|
||||
}
|
||||
|
||||
pub fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) {
|
||||
@ -49,6 +53,7 @@ pub fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) {
|
||||
pub struct Triangler {
|
||||
pub program: <glow::Context as HasContext>::Program,
|
||||
pub vertex_array: <glow::Context as HasContext>::VertexArray,
|
||||
is_gles: bool,
|
||||
}
|
||||
|
||||
impl Triangler {
|
||||
@ -61,18 +66,50 @@ const vec2 verts[3] = vec2[3](
|
||||
);
|
||||
|
||||
out vec2 vert;
|
||||
out vec4 color;
|
||||
|
||||
vec4 srgb_to_linear(vec4 srgb_color) {
|
||||
// Calcuation as documented by OpenGL
|
||||
vec3 srgb = srgb_color.rgb;
|
||||
vec3 selector = ceil(srgb - 0.04045);
|
||||
vec3 less_than_branch = srgb / 12.92;
|
||||
vec3 greater_than_branch = pow((srgb + 0.055) / 1.055, vec3(2.4));
|
||||
return vec4(
|
||||
mix(less_than_branch, greater_than_branch, selector),
|
||||
srgb_color.a
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vert = verts[gl_VertexID];
|
||||
color = srgb_to_linear(vec4(vert, 0.5, 1.0));
|
||||
gl_Position = vec4(vert - 0.5, 0.0, 1.0);
|
||||
}
|
||||
"#;
|
||||
const FRAGMENT_SHADER_SOURCE: &str = r#"
|
||||
in vec2 vert;
|
||||
out vec4 colour;
|
||||
in vec4 color;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
vec4 linear_to_srgb(vec4 linear_color) {
|
||||
#ifdef IS_GLES
|
||||
vec3 linear = linear_color.rgb;
|
||||
vec3 selector = ceil(linear - 0.0031308);
|
||||
vec3 less_than_branch = linear * 12.92;
|
||||
vec3 greater_than_branch = pow(linear, vec3(1.0/2.4)) * 1.055 - 0.055;
|
||||
return vec4(
|
||||
mix(less_than_branch, greater_than_branch, selector),
|
||||
linear_color.a
|
||||
);
|
||||
#else
|
||||
// For non-GLES, GL_FRAMEBUFFER_SRGB handles this for free
|
||||
return linear_color;
|
||||
#endif
|
||||
}
|
||||
|
||||
void main() {
|
||||
colour = vec4(vert, 0.5, 1.0);
|
||||
frag_color = linear_to_srgb(color);
|
||||
}
|
||||
"#;
|
||||
|
||||
@ -112,13 +149,21 @@ void main() {
|
||||
Self {
|
||||
program,
|
||||
vertex_array,
|
||||
is_gles: imgui_glow_renderer::versions::GlVersion::read(gl).is_gles,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&self, gl: &glow::Context) {
|
||||
unsafe {
|
||||
gl.clear_color(0.05, 0.05, 0.1, 1.0);
|
||||
if self.is_gles {
|
||||
// Specify clear color in sRGB space, since GL_FRAMEBUFFER_SRGB
|
||||
// is not supported
|
||||
gl.clear_color(0.05, 0.05, 0.1, 1.0);
|
||||
} else {
|
||||
// Specify clear color in linear space
|
||||
gl.clear_color(0.004, 0.004, 0.01, 1.0);
|
||||
}
|
||||
gl.clear(glow::COLOR_BUFFER_BIT);
|
||||
gl.use_program(Some(self.program));
|
||||
gl.bind_vertex_array(Some(self.vertex_array));
|
||||
|
||||
@ -793,9 +793,22 @@ uniform mat4 matrix;
|
||||
out vec2 fragment_uv;
|
||||
out vec4 fragment_color;
|
||||
|
||||
// Because imgui only specifies linear colors
|
||||
vec4 srgb_to_linear(vec4 srgb_color) {
|
||||
// Calcuation as documented by OpenGL
|
||||
vec3 srgb = srgb_color.rgb;
|
||||
vec3 selector = ceil(srgb - 0.04045);
|
||||
vec3 less_than_branch = srgb / 12.92;
|
||||
vec3 greater_than_branch = pow((srgb + 0.055) / 1.055, vec3(2.4));
|
||||
return vec4(
|
||||
mix(less_than_branch, greater_than_branch, selector),
|
||||
srgb_color.a
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
fragment_uv = uv;
|
||||
fragment_color = color;
|
||||
fragment_color = srgb_to_linear(color);
|
||||
gl_Position = matrix * vec4(position.xy, 0, 1);
|
||||
}
|
||||
"#;
|
||||
@ -806,8 +819,24 @@ in vec4 fragment_color;
|
||||
uniform sampler2D tex;
|
||||
layout (location = 0) out vec4 out_color;
|
||||
|
||||
vec4 linear_to_srgb(vec4 linear_color) {
|
||||
#ifdef IS_GLES
|
||||
vec3 linear = linear_color.rgb;
|
||||
vec3 selector = ceil(linear - 0.0031308);
|
||||
vec3 less_than_branch = linear * 12.92;
|
||||
vec3 greater_than_branch = pow(linear, vec3(1.0/2.4)) * 1.055 - 0.055;
|
||||
return vec4(
|
||||
mix(less_than_branch, greater_than_branch, selector),
|
||||
linear_color.a
|
||||
);
|
||||
#else
|
||||
// For non-GLES, GL_FRAMEBUFFER_SRGB handles this for free
|
||||
return linear_color;
|
||||
#endif
|
||||
}
|
||||
|
||||
void main() {
|
||||
out_color = fragment_color * texture(tex, fragment_uv.st);
|
||||
out_color = linear_to_srgb(fragment_color * texture(tex, fragment_uv.st));
|
||||
}
|
||||
"#;
|
||||
|
||||
@ -854,7 +883,7 @@ void main() {
|
||||
major = major,
|
||||
minor = minor * 10,
|
||||
es_extras = if is_gles {
|
||||
" es\nprecision mediump float;"
|
||||
" es\nprecision mediump float;\n#define IS_GLES"
|
||||
} else {
|
||||
""
|
||||
},
|
||||
@ -968,14 +997,14 @@ fn prepare_font_atlas<G: Gl, T: TextureMap>(
|
||||
gl.tex_image_2d(
|
||||
glow::TEXTURE_2D,
|
||||
0,
|
||||
glow::RGBA as _,
|
||||
glow::SRGB8_ALPHA8 as _,
|
||||
atlas_texture.width as _,
|
||||
atlas_texture.height as _,
|
||||
0,
|
||||
glow::RGBA,
|
||||
glow::UNSIGNED_BYTE,
|
||||
Some(atlas_texture.data),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
fonts.tex_id = texture_map
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user