summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs1
-rw-r--r--src/shadow.rs127
2 files changed, 128 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 781d0c0..fb98cb2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,6 +11,7 @@ pub mod mesh;
pub mod texture;
pub mod font;
pub mod audio;
+pub mod shadow;
pub fn run<F, G>(gnew: F) where G: state::Game + 'static, F: (Fn(&context::Context) -> G) {
console_log::init_with_level(log::Level::Debug).unwrap();
diff --git a/src/shadow.rs b/src/shadow.rs
new file mode 100644
index 0000000..f827967
--- /dev/null
+++ b/src/shadow.rs
@@ -0,0 +1,127 @@
+use glow::HasContext;
+
+use crate::context;
+
+pub struct ShadowBuffer {
+ pub fbo: glow::Framebuffer,
+ pub depth_tex: glow::Texture,
+ pub width: i32,
+ pub height: i32,
+}
+
+impl ShadowBuffer {
+ pub fn new(ctx: &context::Context, w: i32, h: i32) -> Self {
+ unsafe {
+ // generate and bind FBO
+ let fbo = ctx.gl.create_framebuffer().expect("failed to create framebuffer");
+ ctx.gl.bind_framebuffer(glow::FRAMEBUFFER, Some(fbo));
+
+ // generate and attach depth buffer
+ let depth_tex = ctx.gl.create_texture().expect("failed to create texture");
+ ctx.gl.bind_texture(glow::TEXTURE_2D, Some(depth_tex));
+ ctx.gl.tex_image_2d(
+ glow::TEXTURE_2D,
+ 0,
+ glow::DEPTH_COMPONENT as i32,
+ w,
+ h,
+ 0,
+ glow::DEPTH_COMPONENT,
+ glow::FLOAT,
+ None,
+ );
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::LINEAR as i32);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::LINEAR as i32);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::CLAMP_TO_BORDER as i32);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, glow::CLAMP_TO_BORDER as i32);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_COMPARE_MODE, glow::COMPARE_REF_TO_TEXTURE as i32);
+ ctx.gl.tex_parameter_f32_slice(glow::TEXTURE_2D, glow::TEXTURE_BORDER_COLOR, &[1.0, 1.0, 1.0, 1.0]);
+ ctx.gl.framebuffer_texture_2d(glow::FRAMEBUFFER, glow::DEPTH_ATTACHMENT, glow::TEXTURE_2D, Some(depth_tex), 0);
+ ctx.gl.draw_buffer(glow::NONE);
+ ctx.gl.read_buffer(glow::NONE);
+
+ let status = ctx.gl.check_framebuffer_status(glow::FRAMEBUFFER);
+ if status != glow::FRAMEBUFFER_COMPLETE {
+ panic!("error initializing framebuffer: {}", status);
+ }
+ Self {
+ fbo,
+ depth_tex,
+ width: w,
+ height: h,
+ }
+ }
+ }
+
+ pub fn bind(&self, ctx: &context::Context) {
+ unsafe {
+ ctx.gl.bind_framebuffer(glow::FRAMEBUFFER, Some(self.fbo));
+ ctx.gl.viewport(0, 0, self.width as _, self.height as _);
+ ctx.gl.clear(glow::DEPTH_BUFFER_BIT);
+
+ }
+ }
+}
+
+pub struct ShadowBuffer3D {
+ pub fbo: glow::Framebuffer,
+ pub depth_cubemap: glow::Texture,
+ pub width: i32,
+ pub height: i32,
+}
+
+impl ShadowBuffer3D {
+ pub fn new(ctx: &context::Context, w: i32, h: i32) -> Self {
+ unsafe {
+ // generate and bind FBO
+ let fbo = ctx.gl.create_framebuffer().expect("failed to create framebuffer");
+ ctx.gl.bind_framebuffer(glow::FRAMEBUFFER, Some(fbo));
+
+ // generate and attach depth buffer
+ let depth_cubemap = ctx.gl.create_texture().expect("failed to create texture");
+ ctx.gl.bind_texture(glow::TEXTURE_CUBE_MAP, Some(depth_cubemap));
+ for i in 0..6 {
+ ctx.gl.tex_image_2d(
+ glow::TEXTURE_CUBE_MAP_POSITIVE_X + i,
+ 0,
+ glow::DEPTH_COMPONENT as i32,
+ w,
+ h,
+ 0,
+ glow::DEPTH_COMPONENT,
+ glow::FLOAT,
+ None,
+ );
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_CUBE_MAP, glow::TEXTURE_MIN_FILTER, glow::LINEAR as i32);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_CUBE_MAP, glow::TEXTURE_MAG_FILTER, glow::LINEAR as i32);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_CUBE_MAP, glow::TEXTURE_WRAP_S, glow::CLAMP_TO_EDGE as i32);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_CUBE_MAP, glow::TEXTURE_WRAP_T, glow::CLAMP_TO_EDGE as i32);
+ ctx.gl.tex_parameter_i32(glow::TEXTURE_CUBE_MAP, glow::TEXTURE_WRAP_R, glow::CLAMP_TO_EDGE as i32);
+ }
+
+ ctx.gl.framebuffer_texture(glow::FRAMEBUFFER, glow::DEPTH_ATTACHMENT, Some(depth_cubemap), 0);
+ ctx.gl.draw_buffer(glow::NONE);
+ ctx.gl.read_buffer(glow::NONE);
+
+ let status = ctx.gl.check_framebuffer_status(glow::FRAMEBUFFER);
+ if status != glow::FRAMEBUFFER_COMPLETE {
+ panic!("error initializing framebuffer: {}", status);
+ }
+ Self {
+ fbo,
+ depth_cubemap,
+ width: w,
+ height: h,
+ }
+ }
+ }
+
+ pub fn bind(&self, ctx: &context::Context) {
+ unsafe {
+ ctx.gl.bind_framebuffer(glow::FRAMEBUFFER, Some(self.fbo));
+ ctx.gl.viewport(0, 0, self.width as _, self.height as _);
+ ctx.gl.clear(glow::DEPTH_BUFFER_BIT);
+
+ }
+ }
+}