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