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