pub struct GBuf {
id: u32,
pos_id: u32,
norm_id: u32,
alb_spec_id: u32,
depth_id: u32,
width: u32,
height: u32,
}
impl GBuf {
pub fn new(width: u32, height: u32) -> Self {
let mut id: u32 = 0;
gl_call!(gl::GenFramebuffers(1, &mut id));
gl_call!(gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, id));
let mut pos_id: u32 = 0;
gl_call!(gl::GenTextures(1, &mut pos_id));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, pos_id));
GBuf::specify_texture(gl::RGBA32F, gl::FLOAT, width, height);
gl_call!(gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MIN_FILTER,
gl::NEAREST as i32
));
gl_call!(gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MAG_FILTER,
gl::NEAREST as i32
));
gl_call!(gl::FramebufferTexture2D(
gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D,
pos_id,
0
));
let mut norm_id: u32 = 0;
gl_call!(gl::GenTextures(1, &mut norm_id));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, norm_id));
GBuf::specify_texture(gl::RGBA32F, gl::FLOAT, width, height);
gl_call!(gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MIN_FILTER,
gl::NEAREST as i32
));
gl_call!(gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MAG_FILTER,
gl::NEAREST as i32
));
gl_call!(gl::FramebufferTexture2D(
gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT1,
gl::TEXTURE_2D,
norm_id,
0
));
let mut alb_spec_id: u32 = 0;
gl_call!(gl::GenTextures(1, &mut alb_spec_id));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, alb_spec_id));
GBuf::specify_texture(gl::RGBA, gl::UNSIGNED_BYTE, width, height);
gl_call!(gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MIN_FILTER,
gl::NEAREST as i32
));
gl_call!(gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MAG_FILTER,
gl::NEAREST as i32
));
gl_call!(gl::FramebufferTexture2D(
gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT2,
gl::TEXTURE_2D,
alb_spec_id,
0
));
let attachments: [u32; 3] = [
gl::COLOR_ATTACHMENT0,
gl::COLOR_ATTACHMENT1,
gl::COLOR_ATTACHMENT2,
];
gl_call!(gl::DrawBuffers(3, attachments.as_ptr()));
let mut depth_id: u32 = 0;
gl_call!(gl::GenRenderbuffers(1, &mut depth_id));
gl_call!(gl::BindRenderbuffer(gl::RENDERBUFFER, depth_id));
gl_call!(gl::RenderbufferStorage(
gl::RENDERBUFFER,
gl::DEPTH_COMPONENT,
width as i32,
height as i32
));
gl_call!(gl::FramebufferRenderbuffer(
gl::FRAMEBUFFER,
gl::DEPTH_ATTACHMENT,
gl::RENDERBUFFER,
depth_id
));
gl_call!(gl::BindRenderbuffer(gl::RENDERBUFFER, 0));
if gl_call!(gl::CheckFramebufferStatus(gl::FRAMEBUFFER) != gl::FRAMEBUFFER_COMPLETE) {
println!("Framebuffer not complete!");
}
gl_call!(gl::BindFramebuffer(gl::FRAMEBUFFER, 0));
GBuf {
id,
pos_id,
norm_id,
alb_spec_id,
depth_id,
width,
height,
}
}
pub fn bind(&self) {
gl_call!(gl::BindFramebuffer(gl::FRAMEBUFFER, self.id));
}
pub fn unbind(&self) {
gl_call!(gl::BindFramebuffer(gl::FRAMEBUFFER, 0));
}
pub fn blit_depth(&self) {
gl_call!(gl::BindFramebuffer(gl::READ_FRAMEBUFFER, self.id));
gl_call!(gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, 0));
gl_call!(gl::BlitFramebuffer(
0,
0,
self.width as i32,
self.height as i32,
0,
0,
self.width as i32,
self.height as i32,
gl::DEPTH_BUFFER_BIT,
gl::NEAREST
));
gl_call!(gl::BindFramebuffer(gl::FRAMEBUFFER, 0));
}
fn specify_texture(
internal_format: gl::types::GLenum,
data_type: gl::types::GLenum,
width: u32,
height: u32,
) {
gl_call!(gl::TexImage2D(
gl::TEXTURE_2D,
0,
internal_format as i32,
width as i32,
height as i32,
0,
gl::RGBA,
data_type,
std::ptr::null()
));
}
pub fn resize(&mut self, width: u32, height: u32) {
self.width = width;
self.height = height;
gl_call!(gl::ActiveTexture(gl::TEXTURE0));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, self.pos_id));
GBuf::specify_texture(gl::RGBA32F, gl::FLOAT, width, height);
gl_call!(gl::BindTexture(gl::TEXTURE_2D, 0));
gl_call!(gl::ActiveTexture(gl::TEXTURE1));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, self.norm_id));
GBuf::specify_texture(gl::RGBA32F, gl::FLOAT, width, height);
gl_call!(gl::BindTexture(gl::TEXTURE_2D, 0));
gl_call!(gl::ActiveTexture(gl::TEXTURE2));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, self.alb_spec_id));
GBuf::specify_texture(gl::RGBA, gl::UNSIGNED_BYTE, width, height);
gl_call!(gl::BindTexture(gl::TEXTURE_2D, 0));
gl_call!(gl::ActiveTexture(gl::TEXTURE0));
gl_call!(gl::BindRenderbuffer(gl::RENDERBUFFER, self.depth_id));
gl_call!(gl::RenderbufferStorage(
gl::RENDERBUFFER,
gl::DEPTH_COMPONENT,
width as i32,
height as i32
));
gl_call!(gl::BindRenderbuffer(gl::RENDERBUFFER, 0));
}
pub fn bind_bufs(&self) {
gl_call!(gl::ActiveTexture(gl::TEXTURE0));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, self.pos_id));
gl_call!(gl::ActiveTexture(gl::TEXTURE1));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, self.norm_id));
gl_call!(gl::ActiveTexture(gl::TEXTURE2));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, self.alb_spec_id));
gl_call!(gl::ActiveTexture(gl::TEXTURE0));
}
pub fn unbind_bufs(&self) {
gl_call!(gl::ActiveTexture(gl::TEXTURE0));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, 0));
gl_call!(gl::ActiveTexture(gl::TEXTURE1));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, 0));
gl_call!(gl::ActiveTexture(gl::TEXTURE2));
gl_call!(gl::BindTexture(gl::TEXTURE_2D, 0));
gl_call!(gl::ActiveTexture(gl::TEXTURE0));
}
}