fixed crash when glDebugCallbackARB is available but glDebugCallback isn't
[laserbrain_demo] / src / shadow.cc
1 #define GPH_NAMESPACE
2 #include <assert.h>
3 #include "opengl.h"
4 #include "shadow.h"
5
6 #undef DBG_USE_VMATH
7
8 #ifdef DBG_USE_VMATH
9 #include "vmath/vmath.h"
10 #else
11 #include "gmath/gmath.h"
12 #endif
13
14
15 bool shadow_pass;
16
17 static int tex_sz, prev_vp[4];
18 static unsigned int fbo, depth_tex, rb_color;
19 static gph::Mat4 shadow_mat;
20
21 bool init_shadow(int sz)
22 {
23         tex_sz = sz;
24         printf("initializing shadow buffer (%dx%d)\n", tex_sz, tex_sz);
25
26         glGenFramebuffers(1, &fbo);
27         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
28
29         const float border_color[] = {1, 1, 1, 1};
30
31         glGenTextures(1, &depth_tex);
32         glBindTexture(GL_TEXTURE_2D, depth_tex);
33         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
34         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
35         glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
36         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
37         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
38         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
39         glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex_sz, tex_sz, 0,
40                         GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
41         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_tex, 0);
42
43         assert(glGetError() == GL_NO_ERROR);
44
45         glDrawBuffer(GL_FALSE);
46         glReadBuffer(GL_FALSE);
47
48         if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
49                 fprintf(stderr, "incomplete framebuffer\n");
50                 return false;
51         }
52
53         glBindFramebuffer(GL_FRAMEBUFFER, 0);
54         glDrawBuffer(GL_BACK);
55         glReadBuffer(GL_BACK);
56         assert(glGetError() == GL_NO_ERROR);
57
58         return true;
59 }
60
61 void destroy_shadow()
62 {
63         glDeleteTextures(1, &depth_tex);
64         glDeleteRenderbuffers(1, &rb_color);
65         glDeleteFramebuffers(1, &fbo);
66 }
67
68 void begin_shadow_pass(const gph::Vec3 &lpos, const gph::Vec3 &ltarg, float lfov, float znear, float zfar)
69 {
70         shadow_pass = true;
71
72         glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
73         glDisable(GL_LIGHTING);
74         glColorMask(0, 0, 0, 0);
75         glDepthMask(1);
76
77 #ifdef DBG_USE_VMATH
78         Matrix4x4 viewmat;
79         glGetFloatv(GL_MODELVIEW_MATRIX, viewmat[0]);
80         viewmat.transpose();
81
82         Matrix4x4 lt_viewmat, lt_projmat;
83         lt_projmat.set_perspective(DEG_TO_RAD(lfov) * 2.0, 1.0, znear, zfar);
84         lt_viewmat.set_lookat(Vector3(lpos.x, lpos.y, lpos.z), Vector3(ltarg.x, ltarg.y, ltarg.z), Vector3(0, 1, 0));
85         Matrix4x4 smat = lt_projmat * lt_viewmat * viewmat.inverse();
86         smat.transpose();
87
88         memcpy(shadow_mat[0], smat[0], 16 * sizeof(float));
89
90         glMatrixMode(GL_PROJECTION);
91         glPushMatrix();
92         glLoadTransposeMatrixf(lt_projmat[0]);
93
94         glMatrixMode(GL_MODELVIEW);
95         glPushMatrix();
96         glLoadTransposeMatrixf(lt_viewmat[0]);
97 #else
98         gph::Mat4 viewmat;
99         glGetFloatv(GL_MODELVIEW_MATRIX, viewmat[0]);
100
101         gph::Mat4 lt_viewmat, lt_projmat;
102         lt_projmat.perspective(gph::deg_to_rad(lfov) * 2.0, 1.0, znear, zfar);
103         lt_viewmat.inv_lookat(lpos, ltarg, gph::Vec3(0, 1, 0));
104         shadow_mat = lt_projmat * lt_viewmat * viewmat.inverse();
105         //shadow_mat = viewmat.inverse() * lt_viewmat * lt_projmat;
106         shadow_mat.print();
107
108         glMatrixMode(GL_PROJECTION);
109         glPushMatrix();
110         glLoadMatrixf(lt_projmat[0]);
111
112         glMatrixMode(GL_MODELVIEW);
113         glPushMatrix();
114         glLoadMatrixf(lt_viewmat[0]);
115 #endif
116
117         glGetIntegerv(GL_VIEWPORT, prev_vp);
118         glViewport(0, 0, tex_sz, tex_sz);
119
120         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
121
122         glPolygonOffset(2, 2);
123         glEnable(GL_POLYGON_OFFSET_FILL);
124
125         glClear(GL_DEPTH_BUFFER_BIT);
126         glUseProgram(0);
127 }
128
129
130 void end_shadow_pass()
131 {
132         shadow_pass = false;
133
134         glBindFramebuffer(GL_FRAMEBUFFER, 0);
135
136         glViewport(prev_vp[0], prev_vp[1], prev_vp[2], prev_vp[3]);
137
138         glMatrixMode(GL_PROJECTION);
139         glPopMatrix();
140         glMatrixMode(GL_MODELVIEW);
141         glPopMatrix();
142
143         glPopAttrib();
144 }
145
146 gph::Mat4 get_shadow_matrix()
147 {
148         return shadow_mat;
149 }
150
151 unsigned int get_shadow_tex()
152 {
153         return depth_tex;
154 }