Enable depth buffer in WebGL backend (#1499)
This is useful when embedding 3D into eframe using egui::PaintCallback
This commit is contained in:
parent
f3e31391e0
commit
5a78213421
3 changed files with 78 additions and 30 deletions
|
@ -111,7 +111,7 @@ impl Painter {
|
|||
// WebGL2 support sRGB default
|
||||
(ShaderVersion::Es300, _) | (ShaderVersion::Es100, true) => unsafe {
|
||||
// Add sRGB support marker for fragment shader
|
||||
if let Some([width, height]) = pp_fb_extent {
|
||||
if let Some(size) = pp_fb_extent {
|
||||
tracing::debug!("WebGL with sRGB enabled. Turning on post processing for linear framebuffer blending.");
|
||||
// install post process to correct sRGB color:
|
||||
(
|
||||
|
@ -119,8 +119,7 @@ impl Painter {
|
|||
gl.clone(),
|
||||
shader_prefix,
|
||||
is_webgl_1,
|
||||
width,
|
||||
height,
|
||||
size,
|
||||
)?),
|
||||
"#define SRGB_SUPPORTED",
|
||||
)
|
||||
|
@ -341,6 +340,7 @@ impl Painter {
|
|||
if let Some(ref mut post_process) = self.post_process {
|
||||
unsafe {
|
||||
post_process.begin(inner_size[0] as i32, inner_size[1] as i32);
|
||||
post_process.bind();
|
||||
}
|
||||
}
|
||||
let size_in_pixels = unsafe { self.prepare_painting(inner_size, pixels_per_point) };
|
||||
|
|
|
@ -12,7 +12,8 @@ pub(crate) struct PostProcess {
|
|||
index_buffer: glow::Buffer,
|
||||
vao: crate::vao::VertexArrayObject,
|
||||
is_webgl_1: bool,
|
||||
texture: glow::Texture,
|
||||
color_texture: glow::Texture,
|
||||
depth_renderbuffer: Option<glow::Renderbuffer>,
|
||||
texture_size: (i32, i32),
|
||||
fbo: glow::Framebuffer,
|
||||
program: glow::Program,
|
||||
|
@ -23,43 +24,40 @@ impl PostProcess {
|
|||
gl: std::rc::Rc<glow::Context>,
|
||||
shader_prefix: &str,
|
||||
is_webgl_1: bool,
|
||||
width: i32,
|
||||
height: i32,
|
||||
[width, height]: [i32; 2],
|
||||
) -> Result<PostProcess, String> {
|
||||
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
|
||||
|
||||
let fbo = gl.create_framebuffer()?;
|
||||
|
||||
gl.bind_framebuffer(glow::FRAMEBUFFER, Some(fbo));
|
||||
|
||||
let texture = gl.create_texture().unwrap();
|
||||
|
||||
gl.bind_texture(glow::TEXTURE_2D, Some(texture));
|
||||
// ----------------------------------------------
|
||||
// Set up color tesxture:
|
||||
|
||||
let color_texture = gl.create_texture()?;
|
||||
gl.bind_texture(glow::TEXTURE_2D, Some(color_texture));
|
||||
gl.tex_parameter_i32(
|
||||
glow::TEXTURE_2D,
|
||||
glow::TEXTURE_WRAP_S,
|
||||
glow::CLAMP_TO_EDGE as i32,
|
||||
);
|
||||
|
||||
gl.tex_parameter_i32(
|
||||
glow::TEXTURE_2D,
|
||||
glow::TEXTURE_WRAP_T,
|
||||
glow::CLAMP_TO_EDGE as i32,
|
||||
);
|
||||
|
||||
gl.tex_parameter_i32(
|
||||
glow::TEXTURE_2D,
|
||||
glow::TEXTURE_MIN_FILTER,
|
||||
glow::NEAREST as i32,
|
||||
);
|
||||
|
||||
gl.tex_parameter_i32(
|
||||
glow::TEXTURE_2D,
|
||||
glow::TEXTURE_MAG_FILTER,
|
||||
glow::NEAREST as i32,
|
||||
);
|
||||
|
||||
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
|
||||
|
||||
let (internal_format, format) = if is_webgl_1 {
|
||||
(glow::SRGB_ALPHA, glow::SRGB_ALPHA)
|
||||
} else {
|
||||
|
@ -83,12 +81,32 @@ impl PostProcess {
|
|||
glow::FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
glow::TEXTURE_2D,
|
||||
Some(texture),
|
||||
Some(color_texture),
|
||||
0,
|
||||
);
|
||||
gl.bind_texture(glow::TEXTURE_2D, None);
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Depth buffer - we only need this when embedding 3D within egui using `egui::PaintCallback`.
|
||||
// TODO: add a setting to enable/disable the depth buffer.
|
||||
|
||||
let with_depth_buffer = true;
|
||||
let depth_renderbuffer = if with_depth_buffer {
|
||||
let depth_renderbuffer = gl.create_renderbuffer()?;
|
||||
gl.bind_renderbuffer(glow::RENDERBUFFER, Some(depth_renderbuffer));
|
||||
gl.renderbuffer_storage(glow::RENDERBUFFER, glow::DEPTH_COMPONENT16, width, height);
|
||||
gl.bind_renderbuffer(glow::RENDERBUFFER, None);
|
||||
Some(depth_renderbuffer)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
gl.bind_framebuffer(glow::FRAMEBUFFER, None);
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
let vert_shader = compile_shader(
|
||||
&gl,
|
||||
glow::VERTEX_SHADER,
|
||||
|
@ -109,9 +127,9 @@ impl PostProcess {
|
|||
)?;
|
||||
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];
|
||||
let positions: Vec<f32> = vec![0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0];
|
||||
|
||||
let indices = vec![0u8, 1, 2, 1, 2, 3];
|
||||
let indices: Vec<u8> = vec![0, 1, 2, 1, 2, 3];
|
||||
|
||||
let pos_buffer = gl.create_buffer()?;
|
||||
gl.bind_buffer(glow::ARRAY_BUFFER, Some(pos_buffer));
|
||||
|
@ -150,7 +168,8 @@ impl PostProcess {
|
|||
index_buffer,
|
||||
vao,
|
||||
is_webgl_1,
|
||||
texture,
|
||||
color_texture,
|
||||
depth_renderbuffer,
|
||||
texture_size: (width, height),
|
||||
fbo,
|
||||
program,
|
||||
|
@ -159,9 +178,9 @@ impl PostProcess {
|
|||
|
||||
pub(crate) unsafe fn begin(&mut self, width: i32, height: i32) {
|
||||
if (width, height) != self.texture_size {
|
||||
self.gl.bind_texture(glow::TEXTURE_2D, Some(self.texture));
|
||||
self.gl
|
||||
.bind_texture(glow::TEXTURE_2D, Some(self.color_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 {
|
||||
|
@ -178,20 +197,45 @@ impl PostProcess {
|
|||
glow::UNSIGNED_BYTE,
|
||||
None,
|
||||
);
|
||||
|
||||
self.gl.bind_texture(glow::TEXTURE_2D, None);
|
||||
self.texture_size = (width, height);
|
||||
|
||||
if let Some(depth_renderbuffer) = self.depth_renderbuffer {
|
||||
self.gl
|
||||
.bind_renderbuffer(glow::RENDERBUFFER, Some(depth_renderbuffer));
|
||||
self.gl.renderbuffer_storage(
|
||||
glow::RENDERBUFFER,
|
||||
glow::DEPTH_COMPONENT16,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
self.gl.bind_renderbuffer(glow::RENDERBUFFER, None);
|
||||
}
|
||||
|
||||
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);
|
||||
self.texture_size = (width, height);
|
||||
}
|
||||
|
||||
check_for_gl_error!(&self.gl, "PostProcess::begin");
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn bind(&self) {
|
||||
self.gl.bind_framebuffer(glow::FRAMEBUFFER, Some(self.fbo));
|
||||
|
||||
self.gl.framebuffer_texture_2d(
|
||||
glow::FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
glow::TEXTURE_2D,
|
||||
Some(self.color_texture),
|
||||
0,
|
||||
);
|
||||
|
||||
self.gl.framebuffer_renderbuffer(
|
||||
glow::FRAMEBUFFER,
|
||||
glow::DEPTH_ATTACHMENT,
|
||||
glow::RENDERBUFFER,
|
||||
self.depth_renderbuffer,
|
||||
);
|
||||
|
||||
check_for_gl_error!(&self.gl, "PostProcess::bind");
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn end(&self) {
|
||||
|
@ -201,7 +245,8 @@ impl PostProcess {
|
|||
self.gl.use_program(Some(self.program));
|
||||
|
||||
self.gl.active_texture(glow::TEXTURE0);
|
||||
self.gl.bind_texture(glow::TEXTURE_2D, Some(self.texture));
|
||||
self.gl
|
||||
.bind_texture(glow::TEXTURE_2D, Some(self.color_texture));
|
||||
let u_sampler_loc = self
|
||||
.gl
|
||||
.get_uniform_location(self.program, "u_sampler")
|
||||
|
@ -226,6 +271,9 @@ impl PostProcess {
|
|||
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);
|
||||
self.gl.delete_texture(self.color_texture);
|
||||
if let Some(depth_renderbuffer) = self.depth_renderbuffer {
|
||||
self.gl.delete_renderbuffer(depth_renderbuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -663,7 +663,7 @@ pub struct PaintCallbackInfo {
|
|||
/// This specifies where on the screen to paint, and the borders of this
|
||||
/// Rect is the [-1, +1] of the Normalized Device Coordinates.
|
||||
///
|
||||
/// Note than only a portion of this may be visible due to [`Self::clip`].
|
||||
/// Note than only a portion of this may be visible due to [`Self::clip_rect`].
|
||||
pub viewport: Rect,
|
||||
|
||||
/// Clip rectangle in points.
|
||||
|
@ -706,12 +706,12 @@ impl PaintCallbackInfo {
|
|||
}
|
||||
}
|
||||
|
||||
/// The viewport rectangle.
|
||||
/// The viewport rectangle. This is what you would use in e.g. `glViewport`.
|
||||
pub fn viewport_in_pixels(&self) -> ViewportInPixels {
|
||||
self.points_to_pixels(&self.viewport)
|
||||
}
|
||||
|
||||
/// The "scissor" or "clip" rectangle.
|
||||
/// The "scissor" or "clip" rectangle. This is what you would use in e.g. `glScissor`.
|
||||
pub fn clip_rect_in_pixels(&self) -> ViewportInPixels {
|
||||
self.points_to_pixels(&self.clip_rect)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue