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