Implement MSAA for triangle meshes in iced_glow
This commit is contained in:
parent
bbfb1c040c
commit
c5545c7a73
@ -4,6 +4,7 @@ use crate::settings;
|
|||||||
use crate::Transformation;
|
use crate::Transformation;
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
use iced_graphics::layer;
|
use iced_graphics::layer;
|
||||||
|
use iced_graphics::Size;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
pub use iced_graphics::triangle::{Mesh2D, Vertex2D};
|
pub use iced_graphics::triangle::{Mesh2D, Vertex2D};
|
||||||
@ -18,6 +19,7 @@ pub(crate) struct Pipeline {
|
|||||||
vertices: Buffer<Vertex2D>,
|
vertices: Buffer<Vertex2D>,
|
||||||
indices: Buffer<u32>,
|
indices: Buffer<u32>,
|
||||||
current_transform: Transformation,
|
current_transform: Transformation,
|
||||||
|
antialias: Antialias,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pipeline {
|
impl Pipeline {
|
||||||
@ -97,6 +99,7 @@ impl Pipeline {
|
|||||||
vertices,
|
vertices,
|
||||||
indices,
|
indices,
|
||||||
current_transform: Transformation::identity(),
|
current_transform: Transformation::identity(),
|
||||||
|
antialias: Antialias::new(antialiasing),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,49 +160,57 @@ impl Pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then we draw each mesh using offsets
|
let Self {
|
||||||
let mut last_vertex = 0;
|
antialias,
|
||||||
let mut last_index = 0;
|
current_transform,
|
||||||
|
..
|
||||||
|
} = self;
|
||||||
|
|
||||||
for layer::Mesh {
|
// Then we draw each mesh using offsets with antialiasing
|
||||||
buffers,
|
antialias.perform(gl, Size::new(target_width, target_height), |gl| {
|
||||||
origin,
|
let mut last_vertex = 0;
|
||||||
clip_bounds,
|
let mut last_index = 0;
|
||||||
} in meshes
|
|
||||||
{
|
|
||||||
let transform =
|
|
||||||
transformation * Transformation::translate(origin.x, origin.y);
|
|
||||||
|
|
||||||
let clip_bounds = (*clip_bounds * scale_factor).round();
|
for layer::Mesh {
|
||||||
|
buffers,
|
||||||
|
origin,
|
||||||
|
clip_bounds,
|
||||||
|
} in meshes
|
||||||
|
{
|
||||||
|
let transform = transformation
|
||||||
|
* Transformation::translate(origin.x, origin.y);
|
||||||
|
|
||||||
unsafe {
|
let clip_bounds = (*clip_bounds * scale_factor).round();
|
||||||
if self.current_transform != transform {
|
|
||||||
let matrix: [f32; 16] = transform.into();
|
|
||||||
gl.uniform_matrix_4_f32_slice(Some(&0), false, &matrix);
|
|
||||||
|
|
||||||
self.current_transform = transform;
|
unsafe {
|
||||||
|
if *current_transform != transform {
|
||||||
|
let matrix: [f32; 16] = transform.into();
|
||||||
|
gl.uniform_matrix_4_f32_slice(Some(&0), false, &matrix);
|
||||||
|
|
||||||
|
*current_transform = transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.scissor(
|
||||||
|
clip_bounds.x as i32,
|
||||||
|
(target_height - (clip_bounds.y + clip_bounds.height))
|
||||||
|
as i32,
|
||||||
|
clip_bounds.width as i32,
|
||||||
|
clip_bounds.height as i32,
|
||||||
|
);
|
||||||
|
|
||||||
|
gl.draw_elements_base_vertex(
|
||||||
|
glow::TRIANGLES,
|
||||||
|
buffers.indices.len() as i32,
|
||||||
|
glow::UNSIGNED_INT,
|
||||||
|
(last_index * std::mem::size_of::<u32>()) as i32,
|
||||||
|
last_vertex as i32,
|
||||||
|
);
|
||||||
|
|
||||||
|
last_vertex += buffers.vertices.len();
|
||||||
|
last_index += buffers.indices.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.scissor(
|
|
||||||
clip_bounds.x as i32,
|
|
||||||
(target_height - (clip_bounds.y + clip_bounds.height))
|
|
||||||
as i32,
|
|
||||||
clip_bounds.width as i32,
|
|
||||||
clip_bounds.height as i32,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.draw_elements_base_vertex(
|
|
||||||
glow::TRIANGLES,
|
|
||||||
buffers.indices.len() as i32,
|
|
||||||
glow::UNSIGNED_INT,
|
|
||||||
(last_index * std::mem::size_of::<u32>()) as i32,
|
|
||||||
last_vertex as i32,
|
|
||||||
);
|
|
||||||
|
|
||||||
last_vertex += buffers.vertices.len();
|
|
||||||
last_index += buffers.indices.len();
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gl.bind_vertex_array(None);
|
gl.bind_vertex_array(None);
|
||||||
@ -279,3 +290,146 @@ impl<T> Buffer<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Antialias {
|
||||||
|
renderbuffer: Option<Renderbuffer>,
|
||||||
|
sample_count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Antialias {
|
||||||
|
fn new(antialiasing: Option<settings::Antialiasing>) -> Self {
|
||||||
|
Antialias {
|
||||||
|
renderbuffer: None,
|
||||||
|
sample_count: antialiasing
|
||||||
|
.map(settings::Antialiasing::sample_count)
|
||||||
|
.unwrap_or(1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn perform(
|
||||||
|
&mut self,
|
||||||
|
gl: &glow::Context,
|
||||||
|
size: Size<u32>,
|
||||||
|
f: impl FnOnce(&glow::Context),
|
||||||
|
) {
|
||||||
|
if self.sample_count == 1 {
|
||||||
|
return f(gl);
|
||||||
|
}
|
||||||
|
|
||||||
|
let target = glow::DRAW_FRAMEBUFFER;
|
||||||
|
|
||||||
|
let renderbuffer = if let Some(renderbuffer) = self.renderbuffer.take()
|
||||||
|
{
|
||||||
|
if size == renderbuffer.size {
|
||||||
|
renderbuffer
|
||||||
|
} else {
|
||||||
|
renderbuffer.destroy(gl);
|
||||||
|
|
||||||
|
Renderbuffer::new(gl, target, self.sample_count, size)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Renderbuffer::new(gl, target, self.sample_count, size)
|
||||||
|
};
|
||||||
|
|
||||||
|
renderbuffer.bind(gl, target);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl.clear_color(0.0, 0.0, 0.0, 0.0);
|
||||||
|
gl.clear(glow::COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
f(gl);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl.bind_framebuffer(target, None);
|
||||||
|
gl.clear_color(1.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderbuffer.blit(gl);
|
||||||
|
|
||||||
|
self.renderbuffer = Some(renderbuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Renderbuffer {
|
||||||
|
raw: <glow::Context as HasContext>::Renderbuffer,
|
||||||
|
framebuffer: <glow::Context as HasContext>::Framebuffer,
|
||||||
|
size: Size<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderbuffer {
|
||||||
|
fn new(
|
||||||
|
gl: &glow::Context,
|
||||||
|
target: u32,
|
||||||
|
sample_count: u32,
|
||||||
|
size: Size<u32>,
|
||||||
|
) -> Self {
|
||||||
|
let framebuffer = unsafe {
|
||||||
|
gl.create_framebuffer().expect("Create MSAA framebuffer")
|
||||||
|
};
|
||||||
|
|
||||||
|
let raw = unsafe {
|
||||||
|
gl.create_renderbuffer().expect("Create MSAA renderbuffer")
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl.bind_renderbuffer(glow::RENDERBUFFER, Some(raw));
|
||||||
|
gl.renderbuffer_storage_multisample(
|
||||||
|
glow::RENDERBUFFER,
|
||||||
|
sample_count as i32,
|
||||||
|
glow::SRGB8_ALPHA8,
|
||||||
|
size.width as i32,
|
||||||
|
size.height as i32,
|
||||||
|
);
|
||||||
|
|
||||||
|
gl.bind_framebuffer(target, Some(framebuffer));
|
||||||
|
gl.framebuffer_renderbuffer(
|
||||||
|
target,
|
||||||
|
glow::COLOR_ATTACHMENT0,
|
||||||
|
glow::RENDERBUFFER,
|
||||||
|
Some(raw),
|
||||||
|
);
|
||||||
|
gl.bind_framebuffer(target, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
raw,
|
||||||
|
framebuffer,
|
||||||
|
size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bind(&self, gl: &glow::Context, target: u32) {
|
||||||
|
unsafe {
|
||||||
|
gl.bind_framebuffer(target, Some(self.framebuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blit(&self, gl: &glow::Context) {
|
||||||
|
unsafe {
|
||||||
|
self.bind(gl, glow::READ_FRAMEBUFFER);
|
||||||
|
|
||||||
|
gl.blit_framebuffer(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
self.size.width as i32,
|
||||||
|
self.size.height as i32,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
self.size.width as i32,
|
||||||
|
self.size.height as i32,
|
||||||
|
glow::COLOR_BUFFER_BIT,
|
||||||
|
glow::NEAREST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn destroy(self, gl: &glow::Context) {
|
||||||
|
unsafe {
|
||||||
|
gl.delete_renderbuffer(self.raw);
|
||||||
|
gl.delete_framebuffer(self.framebuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user