summaryrefslogtreecommitdiff
path: root/src/framebuffer.rs
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2024-03-03 00:10:10 -0500
committerLLLL Colonq <llll@colonq>2024-03-03 00:10:10 -0500
commit070108cf09b1b561613b6eea04723afbbb464507 (patch)
tree01503df63f16ef6ef4ab4a37b24305286bb2477c /src/framebuffer.rs
Initial commit (new winit)
Diffstat (limited to 'src/framebuffer.rs')
-rw-r--r--src/framebuffer.rs100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/framebuffer.rs b/src/framebuffer.rs
new file mode 100644
index 0000000..c0ac72b
--- /dev/null
+++ b/src/framebuffer.rs
@@ -0,0 +1,100 @@
+use glow::HasContext;
+
+use crate::context;
+
+pub struct Framebuffer {
+ pub tex: Option<glow::Texture>,
+ pub fbo: Option<glow::Framebuffer>,
+ pub dims: glam::Vec2,
+ pub offsets: glam::Vec2,
+}
+
+impl Framebuffer {
+ pub fn screen(ctx: &context::Context) -> Self {
+ let (windoww, windowh): (f32, f32) = ctx.window.inner_size().into();
+ let ratio = context::compute_upscale(windoww as _, windowh as _) as f32;
+ let upscalew = context::RENDER_WIDTH * ratio;
+ let upscaleh = context::RENDER_HEIGHT * ratio;
+ let offsetx = (windoww - upscalew) / 2.0;
+ let offsety = (windowh - upscaleh) / 2.0;
+ log::info!("{} {} {} {} {} {}", windoww, windowh, upscalew, upscaleh, offsetx, offsety);
+ Self {
+ tex: None,
+ fbo: None,
+ dims: glam::Vec2::new(upscalew, upscaleh),
+ offsets: glam::Vec2::new(offsetx, offsety),
+ }
+ }
+
+ pub fn new(ctx: &context::Context, dims: &glam::Vec2, offsets: &glam::Vec2) -> Self {
+ unsafe {
+ let fbo = ctx.gl.create_framebuffer()
+ .expect("failed to create framebuffer");
+ ctx.gl.bind_framebuffer(glow::FRAMEBUFFER, Some(fbo));
+
+ let depth_buffer = ctx.gl.create_renderbuffer()
+ .expect("failed to create depth buffer");
+ ctx.gl.bind_renderbuffer(glow::RENDERBUFFER, Some(depth_buffer));
+ ctx.gl.renderbuffer_storage(glow::RENDERBUFFER, glow::DEPTH_COMPONENT32F, dims.x as _, dims.y as _);
+ ctx.gl.framebuffer_renderbuffer(glow::FRAMEBUFFER, glow::DEPTH_ATTACHMENT, glow::RENDERBUFFER, Some(depth_buffer));
+
+ let stencil_buffer = ctx.gl.create_renderbuffer()
+ .expect("failed to create stencil buffer");
+ ctx.gl.bind_renderbuffer(glow::RENDERBUFFER, Some(stencil_buffer));
+ ctx.gl.renderbuffer_storage(glow::RENDERBUFFER, glow::DEPTH_STENCIL, dims.x as _, dims.y as _);
+ ctx.gl.framebuffer_renderbuffer(glow::FRAMEBUFFER, glow::DEPTH_STENCIL_ATTACHMENT, glow::RENDERBUFFER, Some(stencil_buffer));
+
+ let tex = ctx.gl.create_texture()
+ .expect("failed to create framebuffer texture");
+ ctx.gl.bind_texture(glow::TEXTURE_2D, Some(tex));
+ ctx.gl.tex_image_2d(
+ glow::TEXTURE_2D,
+ 0,
+ glow::RGBA as _,
+ dims.x as _,
+ dims.y as _,
+ 0,
+ glow::RGBA,
+ glow::UNSIGNED_BYTE,
+ None,
+ );
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::CLAMP_TO_EDGE as _);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, glow::CLAMP_TO_EDGE as _);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::NEAREST as _);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST as _);
+ ctx.gl.framebuffer_texture_2d(glow::FRAMEBUFFER, glow::COLOR_ATTACHMENT0, glow::TEXTURE_2D, Some(tex), 0);
+ ctx.gl.draw_buffer(glow::COLOR_ATTACHMENT0);
+
+ let status = ctx.gl.check_framebuffer_status(glow::FRAMEBUFFER);
+ if status != glow::FRAMEBUFFER_COMPLETE {
+ panic!("error initializing framebuffer:\n{}", status);
+ }
+
+ Self {
+ tex: Some(tex),
+ fbo: Some(fbo),
+ dims: dims.clone(),
+ offsets: offsets.clone(),
+ }
+ }
+ }
+
+ pub fn bind_texture(&self, ctx: &context::Context) {
+ unsafe {
+ ctx.gl.active_texture(glow::TEXTURE0);
+ ctx.gl.bind_texture(glow::TEXTURE_2D, self.tex);
+ }
+ }
+
+ pub fn bind(&self, ctx: &context::Context) {
+ unsafe {
+ ctx.gl.bind_framebuffer(glow::FRAMEBUFFER, self.fbo);
+ ctx.gl.viewport(
+ self.offsets.x as _,
+ self.offsets.y as _,
+ self.dims.x as _,
+ self.dims.y as _,
+ );
+ }
+ }
+}