1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 13:20:05 -04:00

Add Shape::Callback to do custom rendering inside of an egui UI (#1351)

* Add Shape::Callback to do custom rendering inside of an egui UI
* Use Rc<glow::Context> everywhere
* Remove trait WebPainter
* Add glow::Context to epi::App::setup
This commit is contained in:
Emil Ernerfeldt
2022-03-14 13:25:11 +01:00
committed by GitHub
parent 002158050b
commit 6aee4997d4
34 changed files with 777 additions and 385 deletions

View File

@@ -6,6 +6,7 @@ use glow::HasContext;
/// Uses a framebuffer to render everything in linear color space and convert it back to `sRGB`
/// in a separate "post processing" step
pub(crate) struct PostProcess {
gl: std::rc::Rc<glow::Context>,
pos_buffer: glow::Buffer,
index_buffer: glow::Buffer,
vertex_array: crate::misc_util::VAO,
@@ -18,7 +19,7 @@ pub(crate) struct PostProcess {
impl PostProcess {
pub(crate) unsafe fn new(
gl: &glow::Context,
gl: std::rc::Rc<glow::Context>,
shader_prefix: &str,
need_to_emulate_vao: bool,
is_webgl_1: bool,
@@ -76,7 +77,7 @@ impl PostProcess {
glow::UNSIGNED_BYTE,
None,
);
check_for_gl_error(gl, "post process texture initialization");
check_for_gl_error(&gl, "post process texture initialization");
gl.framebuffer_texture_2d(
glow::FRAMEBUFFER,
@@ -89,7 +90,7 @@ impl PostProcess {
gl.bind_framebuffer(glow::FRAMEBUFFER, None);
let vert_shader = compile_shader(
gl,
&gl,
glow::VERTEX_SHADER,
&format!(
"{}\n{}",
@@ -98,7 +99,7 @@ impl PostProcess {
),
)?;
let frag_shader = compile_shader(
gl,
&gl,
glow::FRAGMENT_SHADER,
&format!(
"{}\n{}",
@@ -106,7 +107,7 @@ impl PostProcess {
include_str!("shader/post_fragment_100es.glsl")
),
)?;
let program = link_program(gl, [vert_shader, frag_shader].iter())?;
let program = link_program(&gl, [vert_shader, frag_shader].iter())?;
let positions = vec![0.0f32, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0];
@@ -126,10 +127,10 @@ impl PostProcess {
let mut vertex_array = if need_to_emulate_vao {
crate::misc_util::VAO::emulated()
} else {
crate::misc_util::VAO::native(gl)
crate::misc_util::VAO::native(&gl)
};
vertex_array.bind_vertex_array(gl);
vertex_array.bind_buffer(gl, &pos_buffer);
vertex_array.bind_vertex_array(&gl);
vertex_array.bind_buffer(&gl, &pos_buffer);
let buffer_info_a_pos = BufferInfo {
location: a_pos_loc,
vector_size: 2,
@@ -138,16 +139,17 @@ impl PostProcess {
stride: 0,
offset: 0,
};
vertex_array.add_new_attribute(gl, buffer_info_a_pos);
vertex_array.add_new_attribute(&gl, buffer_info_a_pos);
let index_buffer = gl.create_buffer()?;
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(index_buffer));
gl.buffer_data_u8_slice(glow::ELEMENT_ARRAY_BUFFER, &indices, glow::STATIC_DRAW);
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None);
check_for_gl_error(gl, "post process initialization");
check_for_gl_error(&gl, "post process initialization");
Ok(PostProcess {
gl,
pos_buffer,
index_buffer,
vertex_array,
@@ -159,17 +161,17 @@ impl PostProcess {
})
}
pub(crate) unsafe fn begin(&mut self, gl: &glow::Context, width: i32, height: i32) {
pub(crate) unsafe fn begin(&mut self, width: i32, height: i32) {
if (width, height) != self.texture_size {
gl.bind_texture(glow::TEXTURE_2D, Some(self.texture));
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
self.gl.bind_texture(glow::TEXTURE_2D, Some(self.texture));
self.gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
let (internal_format, format) = if self.is_webgl_1 {
(glow::SRGB_ALPHA, glow::SRGB_ALPHA)
} else {
(glow::SRGB8_ALPHA8, glow::RGBA)
};
gl.tex_image_2d(
self.gl.tex_image_2d(
glow::TEXTURE_2D,
0,
internal_format as i32,
@@ -181,40 +183,49 @@ impl PostProcess {
None,
);
gl.bind_texture(glow::TEXTURE_2D, None);
self.gl.bind_texture(glow::TEXTURE_2D, None);
self.texture_size = (width, height);
}
gl.bind_framebuffer(glow::FRAMEBUFFER, Some(self.fbo));
gl.clear_color(0.0, 0.0, 0.0, 0.0);
gl.clear(glow::COLOR_BUFFER_BIT);
self.gl.bind_framebuffer(glow::FRAMEBUFFER, Some(self.fbo));
self.gl.clear_color(0.0, 0.0, 0.0, 0.0);
self.gl.clear(glow::COLOR_BUFFER_BIT);
}
pub(crate) unsafe fn end(&self, gl: &glow::Context) {
gl.bind_framebuffer(glow::FRAMEBUFFER, None);
gl.disable(glow::SCISSOR_TEST);
gl.use_program(Some(self.program));
gl.active_texture(glow::TEXTURE0);
gl.bind_texture(glow::TEXTURE_2D, Some(self.texture));
let u_sampler_loc = gl.get_uniform_location(self.program, "u_sampler").unwrap();
gl.uniform_1_i32(Some(&u_sampler_loc), 0);
self.vertex_array.bind_vertex_array(gl);
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.index_buffer));
gl.draw_elements(glow::TRIANGLES, 6, glow::UNSIGNED_BYTE, 0);
self.vertex_array.unbind_vertex_array(gl);
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None);
gl.bind_texture(glow::TEXTURE_2D, None);
gl.use_program(None);
pub(crate) unsafe fn bind(&self) {
self.gl.bind_framebuffer(glow::FRAMEBUFFER, Some(self.fbo));
}
pub(crate) unsafe fn destroy(&self, gl: &glow::Context) {
gl.delete_buffer(self.pos_buffer);
gl.delete_buffer(self.index_buffer);
gl.delete_program(self.program);
gl.delete_framebuffer(self.fbo);
gl.delete_texture(self.texture);
pub(crate) unsafe fn end(&self) {
self.gl.bind_framebuffer(glow::FRAMEBUFFER, None);
self.gl.disable(glow::SCISSOR_TEST);
self.gl.use_program(Some(self.program));
self.gl.active_texture(glow::TEXTURE0);
self.gl.bind_texture(glow::TEXTURE_2D, Some(self.texture));
let u_sampler_loc = self
.gl
.get_uniform_location(self.program, "u_sampler")
.unwrap();
self.gl.uniform_1_i32(Some(&u_sampler_loc), 0);
self.vertex_array.bind_vertex_array(&self.gl);
self.gl
.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.index_buffer));
self.gl
.draw_elements(glow::TRIANGLES, 6, glow::UNSIGNED_BYTE, 0);
self.vertex_array.unbind_vertex_array(&self.gl);
self.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None);
self.gl.bind_texture(glow::TEXTURE_2D, None);
self.gl.use_program(None);
}
pub(crate) unsafe fn destroy(&self) {
self.gl.delete_buffer(self.pos_buffer);
self.gl.delete_buffer(self.index_buffer);
self.gl.delete_program(self.program);
self.gl.delete_framebuffer(self.fbo);
self.gl.delete_texture(self.texture);
}
}