Fix sRGB blending and cleanup the relevant code (#2070)
* Fix sRGBA blending on Mac * Clean up handling of sRGB support * Assume sRGB support if any extension has sRGB in it * improve logging very slightly
This commit is contained in:
parent
4aae638e15
commit
990a8c8b44
2 changed files with 54 additions and 44 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
#![allow(clippy::collapsible_else_if)]
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
@ -53,7 +54,7 @@ pub struct Painter {
|
||||||
is_webgl_1: bool,
|
is_webgl_1: bool,
|
||||||
is_embedded: bool,
|
is_embedded: bool,
|
||||||
vao: crate::vao::VertexArrayObject,
|
vao: crate::vao::VertexArrayObject,
|
||||||
srgb_support: bool,
|
srgb_textures: bool,
|
||||||
post_process: Option<PostProcess>,
|
post_process: Option<PostProcess>,
|
||||||
vbo: glow::Buffer,
|
vbo: glow::Buffer,
|
||||||
element_array_buffer: glow::Buffer,
|
element_array_buffer: glow::Buffer,
|
||||||
|
@ -112,45 +113,41 @@ impl Painter {
|
||||||
crate::check_for_gl_error_even_in_release!(&gl, "before Painter::new");
|
crate::check_for_gl_error_even_in_release!(&gl, "before Painter::new");
|
||||||
|
|
||||||
let max_texture_side = unsafe { gl.get_parameter_i32(glow::MAX_TEXTURE_SIZE) } as usize;
|
let max_texture_side = unsafe { gl.get_parameter_i32(glow::MAX_TEXTURE_SIZE) } as usize;
|
||||||
let shader = shader_version.unwrap_or_else(|| ShaderVersion::get(&gl));
|
let shader_version = shader_version.unwrap_or_else(|| ShaderVersion::get(&gl));
|
||||||
let is_webgl_1 = shader == ShaderVersion::Es100;
|
let is_webgl_1 = shader_version == ShaderVersion::Es100;
|
||||||
let header = shader.version_declaration();
|
let header = shader_version.version_declaration();
|
||||||
tracing::debug!("Shader header: {:?}.", header);
|
tracing::debug!("Shader header: {:?}.", header);
|
||||||
// Previously checking srgb_support on WebGL only, now we have to check on other GL | ES as well.
|
|
||||||
let srgb_support = gl.supported_extensions().contains("EXT_sRGB")
|
|
||||||
|| gl.supported_extensions().contains("GL_EXT_sRGB")
|
|
||||||
|| gl
|
|
||||||
.supported_extensions()
|
|
||||||
.contains("GL_ARB_framebuffer_sRGB");
|
|
||||||
tracing::debug!("SRGB Support: {:?}.", srgb_support);
|
|
||||||
|
|
||||||
let (post_process, srgb_support_define) = match (shader, srgb_support) {
|
let supported_extensions = gl.supported_extensions();
|
||||||
// WebGL2 support sRGB default
|
tracing::trace!("OpenGL extensions: {supported_extensions:?}");
|
||||||
(ShaderVersion::Es300, _) | (ShaderVersion::Es100, true) => unsafe {
|
let srgb_textures = shader_version == ShaderVersion::Es300 // WebGL2 always support sRGB
|
||||||
// Add sRGB support marker for fragment shader
|
|| supported_extensions.iter().any(|extension| {
|
||||||
|
// EXT_sRGB, GL_ARB_framebuffer_sRGB, GL_EXT_sRGB, GL_EXT_texture_sRGB_decode, …
|
||||||
|
extension.contains("sRGB")
|
||||||
|
});
|
||||||
|
tracing::debug!("SRGB Support: {:?}", srgb_textures);
|
||||||
|
|
||||||
|
let (post_process, srgb_support_define) = if shader_version.is_embedded() {
|
||||||
|
// WebGL doesn't support linear framebuffer blending… but maybe we can emulate it with `PostProcess`?
|
||||||
|
|
||||||
if let Some(size) = pp_fb_extent {
|
if let Some(size) = pp_fb_extent {
|
||||||
tracing::debug!("WebGL with sRGB enabled. Turning on post processing for linear framebuffer blending.");
|
tracing::debug!("WebGL with sRGB support. Turning on post processing for linear framebuffer blending.");
|
||||||
// install post process to correct sRGB color:
|
// install post process to correct sRGB color:
|
||||||
(
|
(
|
||||||
Some(PostProcess::new(
|
Some(unsafe { PostProcess::new(gl.clone(), shader_prefix, is_webgl_1, size)? }),
|
||||||
gl.clone(),
|
|
||||||
shader_prefix,
|
|
||||||
is_webgl_1,
|
|
||||||
size,
|
|
||||||
)?),
|
|
||||||
"#define SRGB_SUPPORTED",
|
"#define SRGB_SUPPORTED",
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
tracing::debug!("WebGL or OpenGL ES detected but PostProcess disabled because dimension is None");
|
tracing::warn!("WebGL or OpenGL ES detected but PostProcess disabled because dimension is None. Linear framebuffer blending will not be supported.");
|
||||||
|
(None, "")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if srgb_textures {
|
||||||
|
(None, "#define SRGB_SUPPORTED")
|
||||||
|
} else {
|
||||||
|
tracing::warn!("sRGB aware texture filtering not available");
|
||||||
(None, "")
|
(None, "")
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
// WebGL1 without sRGB support disable postprocess and use fallback shader
|
|
||||||
(ShaderVersion::Es100, false) => (None, ""),
|
|
||||||
|
|
||||||
// OpenGL 2.1 or above always support sRGB so add sRGB support marker
|
|
||||||
_ => (None, "#define SRGB_SUPPORTED"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -161,7 +158,7 @@ impl Painter {
|
||||||
"{}\n{}\n{}\n{}",
|
"{}\n{}\n{}\n{}",
|
||||||
header,
|
header,
|
||||||
shader_prefix,
|
shader_prefix,
|
||||||
if shader.is_new_shader_interface() {
|
if shader_version.is_new_shader_interface() {
|
||||||
"#define NEW_SHADER_INTERFACE\n"
|
"#define NEW_SHADER_INTERFACE\n"
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
|
@ -177,7 +174,7 @@ impl Painter {
|
||||||
header,
|
header,
|
||||||
shader_prefix,
|
shader_prefix,
|
||||||
srgb_support_define,
|
srgb_support_define,
|
||||||
if shader.is_new_shader_interface() {
|
if shader_version.is_new_shader_interface() {
|
||||||
"#define NEW_SHADER_INTERFACE\n"
|
"#define NEW_SHADER_INTERFACE\n"
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
|
@ -239,9 +236,9 @@ impl Painter {
|
||||||
u_screen_size,
|
u_screen_size,
|
||||||
u_sampler,
|
u_sampler,
|
||||||
is_webgl_1,
|
is_webgl_1,
|
||||||
is_embedded: matches!(shader, ShaderVersion::Es100 | ShaderVersion::Es300),
|
is_embedded: shader_version.is_embedded(),
|
||||||
vao,
|
vao,
|
||||||
srgb_support,
|
srgb_textures,
|
||||||
post_process,
|
post_process,
|
||||||
vbo,
|
vbo,
|
||||||
element_array_buffer,
|
element_array_buffer,
|
||||||
|
@ -591,16 +588,16 @@ impl Painter {
|
||||||
check_for_gl_error!(&self.gl, "tex_parameter");
|
check_for_gl_error!(&self.gl, "tex_parameter");
|
||||||
|
|
||||||
let (internal_format, src_format) = if self.is_webgl_1 {
|
let (internal_format, src_format) = if self.is_webgl_1 {
|
||||||
let format = if self.srgb_support {
|
let format = if self.srgb_textures {
|
||||||
glow::SRGB_ALPHA
|
glow::SRGB_ALPHA
|
||||||
} else {
|
} else {
|
||||||
glow::RGBA
|
glow::RGBA
|
||||||
};
|
};
|
||||||
(format, format)
|
(format, format)
|
||||||
} else if !self.srgb_support {
|
} else if self.srgb_textures {
|
||||||
(glow::RGBA8, glow::RGBA)
|
|
||||||
} else {
|
|
||||||
(glow::SRGB8_ALPHA8, glow::RGBA)
|
(glow::SRGB8_ALPHA8, glow::RGBA)
|
||||||
|
} else {
|
||||||
|
(glow::RGBA8, glow::RGBA)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
|
self.gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
|
||||||
|
|
|
@ -7,8 +7,14 @@ use std::convert::TryInto;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum ShaderVersion {
|
pub enum ShaderVersion {
|
||||||
Gl120,
|
Gl120,
|
||||||
|
|
||||||
|
/// OpenGL 1.4 or later
|
||||||
Gl140,
|
Gl140,
|
||||||
|
|
||||||
|
/// e.g. WebGL1
|
||||||
Es100,
|
Es100,
|
||||||
|
|
||||||
|
/// e.g. WebGL2
|
||||||
Es300,
|
Es300,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +76,13 @@ impl ShaderVersion {
|
||||||
Self::Es300 | Self::Gl140 => true,
|
Self::Es300 | Self::Gl140 => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_embedded(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Gl120 | Self::Gl140 => false,
|
||||||
|
Self::Es100 | Self::Es300 => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue