Skip to content

Commit

Permalink
Add support for mipmap textures. (emilk#5146)
Browse files Browse the repository at this point in the history
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

* [x] I have followed the instructions in the PR template

Adds support for mipmaps in the `glow` backend.

Should be possible to implement for `wgpu` in the future as well, but
requires a custom compute kernel.
  • Loading branch information
nolanderc committed Sep 22, 2024
1 parent 07ccf41 commit 6f7b9b9
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 7 deletions.
23 changes: 16 additions & 7 deletions crates/egui_glow/src/painter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ const VERT_SRC: &str = include_str!("shader/vertex.glsl");
const FRAG_SRC: &str = include_str!("shader/fragment.glsl");

trait TextureFilterExt {
fn glow_code(&self) -> u32;
fn glow_code(&self, mipmap: Option<egui::TextureFilter>) -> u32;
}

impl TextureFilterExt for egui::TextureFilter {
fn glow_code(&self) -> u32 {
match self {
Self::Linear => glow::LINEAR,
Self::Nearest => glow::NEAREST,
fn glow_code(&self, mipmap: Option<egui::TextureFilter>) -> u32 {
match (self, mipmap) {
(Self::Linear, None) => glow::LINEAR,
(Self::Nearest, None) => glow::NEAREST,
(Self::Linear, Some(Self::Linear)) => glow::LINEAR_MIPMAP_LINEAR,
(Self::Nearest, Some(Self::Linear)) => glow::NEAREST_MIPMAP_LINEAR,
(Self::Linear, Some(Self::Nearest)) => glow::LINEAR_MIPMAP_NEAREST,
(Self::Nearest, Some(Self::Nearest)) => glow::NEAREST_MIPMAP_NEAREST,
}
}
}
Expand Down Expand Up @@ -569,12 +573,12 @@ impl Painter {
self.gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_MAG_FILTER,
options.magnification.glow_code() as i32,
options.magnification.glow_code(None) as i32,
);
self.gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_MIN_FILTER,
options.minification.glow_code() as i32,
options.minification.glow_code(options.mipmap_mode) as i32,
);

self.gl.tex_parameter_i32(
Expand Down Expand Up @@ -635,6 +639,11 @@ impl Painter {
);
check_for_gl_error!(&self.gl, "tex_image_2d");
}

if options.mipmap_mode.is_some() {
self.gl.generate_mipmap(glow::TEXTURE_2D);
check_for_gl_error!(&self.gl, "generate_mipmap");
}
}
}

Expand Down
23 changes: 23 additions & 0 deletions crates/epaint/src/textures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,16 @@ pub struct TextureOptions {

/// How to wrap the texture when the texture coordinates are outside the [0, 1] range.
pub wrap_mode: TextureWrapMode,

/// How to filter between texture mipmaps.
///
/// Mipmaps ensures textures look smooth even when the texture is very small and pixels are much
/// larger than individual texels.
///
/// # Notes
///
/// - This may not be available on all backends (currently only `egui_glow`).
pub mipmap_mode: Option<TextureFilter>,
}

impl TextureOptions {
Expand All @@ -167,42 +177,55 @@ impl TextureOptions {
magnification: TextureFilter::Linear,
minification: TextureFilter::Linear,
wrap_mode: TextureWrapMode::ClampToEdge,
mipmap_mode: None,
};

/// Nearest magnification and minification.
pub const NEAREST: Self = Self {
magnification: TextureFilter::Nearest,
minification: TextureFilter::Nearest,
wrap_mode: TextureWrapMode::ClampToEdge,
mipmap_mode: None,
};

/// Linear magnification and minification, but with the texture repeated.
pub const LINEAR_REPEAT: Self = Self {
magnification: TextureFilter::Linear,
minification: TextureFilter::Linear,
wrap_mode: TextureWrapMode::Repeat,
mipmap_mode: None,
};

/// Linear magnification and minification, but with the texture mirrored and repeated.
pub const LINEAR_MIRRORED_REPEAT: Self = Self {
magnification: TextureFilter::Linear,
minification: TextureFilter::Linear,
wrap_mode: TextureWrapMode::MirroredRepeat,
mipmap_mode: None,
};

/// Nearest magnification and minification, but with the texture repeated.
pub const NEAREST_REPEAT: Self = Self {
magnification: TextureFilter::Nearest,
minification: TextureFilter::Nearest,
wrap_mode: TextureWrapMode::Repeat,
mipmap_mode: None,
};

/// Nearest magnification and minification, but with the texture mirrored and repeated.
pub const NEAREST_MIRRORED_REPEAT: Self = Self {
magnification: TextureFilter::Nearest,
minification: TextureFilter::Nearest,
wrap_mode: TextureWrapMode::MirroredRepeat,
mipmap_mode: None,
};

pub const fn with_mipmap_mode(self, mipmap_mode: Option<TextureFilter>) -> Self {
Self {
mipmap_mode,
..self
}
}
}

impl Default for TextureOptions {
Expand Down

0 comments on commit 6f7b9b9

Please sign in to comment.