shadows, textures, resource managers... shaders...
[antikythera] / src / shadow.cc
diff --git a/src/shadow.cc b/src/shadow.cc
new file mode 100644 (file)
index 0000000..357ed82
--- /dev/null
@@ -0,0 +1,147 @@
+#define GPH_NAMESPACE
+#include <assert.h>
+#include "opengl.h"
+#include "shadow.h"
+#include "vmath/vmath.h"
+
+
+bool shadow_pass;
+
+static int tex_sz, prev_vp[4];
+static unsigned int fbo, depth_tex, rb_color;
+static gph::Mat4 shadow_mat;
+
+bool init_shadow(int sz)
+{
+       tex_sz = sz;
+       printf("initializing shadow buffer (%dx%d)\n", tex_sz, tex_sz);
+
+       glGenFramebuffers(1, &fbo);
+       glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+       const float border_color[] = {1, 1, 1, 1};
+
+       glGenTextures(1, &depth_tex);
+       glBindTexture(GL_TEXTURE_2D, depth_tex);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+       glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex_sz, tex_sz, 0,
+                       GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
+       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_tex, 0);
+
+       assert(glGetError() == GL_NO_ERROR);
+
+       glDrawBuffer(GL_FALSE);
+       glReadBuffer(GL_FALSE);
+
+       if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+               fprintf(stderr, "incomplete framebuffer\n");
+               return false;
+       }
+
+       glBindFramebuffer(GL_FRAMEBUFFER, 0);
+       glDrawBuffer(GL_BACK);
+       glReadBuffer(GL_BACK);
+       assert(glGetError() == GL_NO_ERROR);
+
+       return true;
+}
+
+void destroy_shadow()
+{
+       glDeleteTextures(1, &depth_tex);
+       glDeleteRenderbuffers(1, &rb_color);
+       glDeleteFramebuffers(1, &fbo);
+}
+
+void begin_shadow_pass(const gph::Vec3 &lpos, const gph::Vec3 &ltarg, float lfov, float znear, float zfar)
+{
+       shadow_pass = true;
+
+       glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
+       glDisable(GL_LIGHTING);
+       glColorMask(0, 0, 0, 0);
+       glDepthMask(1);
+
+       Matrix4x4 viewmat;
+       glGetFloatv(GL_MODELVIEW_MATRIX, viewmat[0]);
+       viewmat.transpose();
+
+       Matrix4x4 lt_viewmat, lt_projmat;
+       lt_projmat.set_perspective(DEG_TO_RAD(lfov) * 2.0, 1.0, znear, zfar);
+       lt_viewmat.set_lookat(Vector3(lpos.x, lpos.y, lpos.z), Vector3(ltarg.x, ltarg.y, ltarg.z), Vector3(0, 1, 0));
+       Matrix4x4 smat = lt_projmat * lt_viewmat * viewmat.inverse();
+       smat.transpose();
+
+       memcpy(shadow_mat[0], smat[0], 16 * sizeof(float));
+
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadTransposeMatrixf(lt_projmat[0]);
+
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       glLoadTransposeMatrixf(lt_viewmat[0]);
+
+
+       /*gph::Mat4 viewmat;
+       glGetFloatv(GL_MODELVIEW_MATRIX, viewmat[0]);
+
+       gph::Mat4 lt_viewmat, lt_projmat;
+       lt_projmat.perspective(deg_to_rad(lfov) * 2.0, 1.0, znear, zfar);
+       lt_viewmat.inv_lookat(lpos, ltarg, gph::Vec3(0, 1, 0));
+       shadow_mat = lt_projmat * lt_viewmat * viewmat.inverse();
+       //shadow_mat = viewmat.inverse() * lt_viewmat * lt_projmat;
+       shadow_mat.print();
+
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadMatrixf(lt_projmat[0]);
+
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       glLoadMatrixf(lt_viewmat[0]);
+       */
+
+       glGetIntegerv(GL_VIEWPORT, prev_vp);
+       glViewport(0, 0, tex_sz, tex_sz);
+
+       glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+       glPolygonOffset(2, 2);
+       glEnable(GL_POLYGON_OFFSET_FILL);
+
+       glClear(GL_DEPTH_BUFFER_BIT);
+       glUseProgram(0);
+}
+
+
+void end_shadow_pass()
+{
+       shadow_pass = false;
+
+       glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+       glViewport(prev_vp[0], prev_vp[1], prev_vp[2], prev_vp[3]);
+
+       glMatrixMode(GL_PROJECTION);
+       glPopMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPopMatrix();
+
+       glPopAttrib();
+}
+
+gph::Mat4 get_shadow_matrix()
+{
+       return shadow_mat;
+}
+
+unsigned int get_shadow_tex()
+{
+       return depth_tex;
+}