nuclear@18: #include nuclear@18: #include "opengl.h" nuclear@18: #include "shadow.h" nuclear@18: #include "vmath/vmath.h" nuclear@18: nuclear@19: bool shadow_pass; nuclear@19: nuclear@18: static int tex_sz, prev_vp[4]; nuclear@18: static unsigned int fbo, depth_tex, rb_color; nuclear@18: static Matrix4x4 shadow_mat; nuclear@18: nuclear@18: bool init_shadow(int sz) nuclear@18: { nuclear@19: if(!glcaps.fbo || !glcaps.shadow) { nuclear@19: return false; nuclear@18: } nuclear@18: nuclear@18: tex_sz = sz; nuclear@19: printf("initializing shadow buffer (%dx%d)\n", tex_sz, tex_sz); nuclear@18: nuclear@18: glGenFramebuffers(1, &fbo); nuclear@18: glBindFramebuffer(GL_FRAMEBUFFER, fbo); nuclear@18: nuclear@18: glGenTextures(1, &depth_tex); nuclear@18: glBindTexture(GL_TEXTURE_2D, depth_tex); nuclear@19: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); nuclear@19: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); nuclear@18: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@18: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@18: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); nuclear@18: glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex_sz, tex_sz, 0, nuclear@18: GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); nuclear@18: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_tex, 0); nuclear@18: nuclear@18: assert(glGetError() == GL_NO_ERROR); nuclear@18: nuclear@18: glDrawBuffer(GL_FALSE); nuclear@18: glReadBuffer(GL_FALSE); nuclear@18: nuclear@18: if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { nuclear@18: fprintf(stderr, "incomplete framebuffer\n"); nuclear@18: return false; nuclear@18: } nuclear@18: nuclear@18: glBindFramebuffer(GL_FRAMEBUFFER, 0); nuclear@18: glDrawBuffer(GL_BACK); nuclear@18: glReadBuffer(GL_BACK); nuclear@18: assert(glGetError() == GL_NO_ERROR); nuclear@18: nuclear@18: return true; nuclear@18: } nuclear@18: nuclear@18: void destroy_shadow() nuclear@18: { nuclear@18: glDeleteTextures(1, &depth_tex); nuclear@18: glDeleteRenderbuffers(1, &rb_color); nuclear@18: glDeleteFramebuffers(1, &fbo); nuclear@18: } nuclear@18: nuclear@18: void begin_shadow_pass(const Vector3 &lpos, const Vector3 <arg, float lfov) nuclear@18: { nuclear@19: shadow_pass = true; nuclear@18: nuclear@18: glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT); nuclear@18: glDisable(GL_LIGHTING); nuclear@18: glColorMask(0, 0, 0, 0); nuclear@18: glDepthMask(1); nuclear@18: nuclear@19: Matrix4x4 viewmat; nuclear@19: glGetFloatv(GL_MODELVIEW_MATRIX, viewmat[0]); nuclear@19: viewmat.transpose(); nuclear@19: nuclear@19: Matrix4x4 lt_viewmat, lt_projmat; nuclear@19: lt_projmat.set_perspective(DEG_TO_RAD(lfov) * 2.0, 1.0, 8.0, 50.0); nuclear@19: lt_viewmat.set_lookat(lpos, ltarg, Vector3(0, 1, 0)); nuclear@19: shadow_mat = lt_projmat * lt_viewmat * viewmat.inverse(); nuclear@18: nuclear@18: glMatrixMode(GL_PROJECTION); nuclear@18: glPushMatrix(); nuclear@19: glLoadTransposeMatrixf(lt_projmat[0]); nuclear@19: nuclear@18: glMatrixMode(GL_MODELVIEW); nuclear@18: glPushMatrix(); nuclear@19: glLoadTransposeMatrixf(lt_viewmat[0]); nuclear@18: nuclear@18: glGetIntegerv(GL_VIEWPORT, prev_vp); nuclear@18: glViewport(0, 0, tex_sz, tex_sz); nuclear@18: nuclear@18: glBindFramebuffer(GL_FRAMEBUFFER, fbo); nuclear@19: nuclear@19: glPolygonOffset(2, 2); nuclear@19: glEnable(GL_POLYGON_OFFSET_FILL); nuclear@19: nuclear@19: glClear(GL_DEPTH_BUFFER_BIT); nuclear@19: glUseProgram(0); nuclear@18: } nuclear@18: nuclear@18: nuclear@18: void end_shadow_pass() nuclear@18: { nuclear@19: shadow_pass = false; nuclear@19: nuclear@18: glBindFramebuffer(GL_FRAMEBUFFER, 0); nuclear@18: nuclear@18: glViewport(prev_vp[0], prev_vp[1], prev_vp[2], prev_vp[3]); nuclear@18: nuclear@18: glMatrixMode(GL_PROJECTION); nuclear@18: glPopMatrix(); nuclear@18: glMatrixMode(GL_MODELVIEW); nuclear@18: glPopMatrix(); nuclear@18: nuclear@18: glPopAttrib(); nuclear@18: } nuclear@18: nuclear@18: Matrix4x4 get_shadow_matrix() nuclear@18: { nuclear@18: return shadow_mat; nuclear@19: nuclear@19: /* nuclear@19: glMatrixMode(GL_MODELVIEW); nuclear@19: glPushMatrix(); nuclear@19: glLoadIdentity(); nuclear@19: gluPerspective(lfov * 2.0, 1.0, 0.5, 50.0); nuclear@19: gluLookAt(lpos.x, lpos.y, lpos.z, ltarg.x, ltarg.y, ltarg.z, 0, 1, 0); nuclear@19: nuclear@19: float mat[16]; nuclear@19: glGetFloatv(GL_MODELVIEW_MATRIX, mat); nuclear@19: nuclear@19: Matrix4x4 res; nuclear@19: memcpy(res[0], mat, sizeof mat); nuclear@19: res.transpose(); nuclear@19: return res; nuclear@19: */ nuclear@18: } nuclear@18: nuclear@18: unsigned int get_shadow_tex() nuclear@18: { nuclear@18: return depth_tex; nuclear@18: }