dungeon_crawler
view prototype/src/renderer.cc @ 77:d89b403f630b
added gamma correction (without dialing the lighting down yet)
fixed the incorrect PointLight sphere radius
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 26 Oct 2012 03:03:52 +0300 |
parents | 67d330038629 |
children | 12a1dcfe91fa |
line source
1 #include <limits.h>
2 #include "opengl.h"
3 #include "renderer.h"
4 #include "level.h"
5 #include "sdr.h"
6 #include "datapath.h"
8 static unsigned int load_sdr(const char *vfname, const char *pfname);
9 static int round_pow2(int x);
11 Renderer *rend;
14 Renderer::Renderer()
15 {
16 fbo = 0;
17 rend_tex = rend_depth = 0;
18 width = height = 0;
19 tex_xsz = tex_ysz = 0;
20 post_sdr = 0;
21 }
23 Renderer::~Renderer()
24 {
25 if(post_sdr) {
26 free_program(post_sdr);
27 }
28 if(rend_tex) {
29 glDeleteTextures(1, &rend_tex);
30 }
31 if(rend_depth) {
32 glDeleteRenderbuffersEXT(1, &rend_depth);
33 }
34 if(fbo) {
35 glDeleteFramebuffersEXT(1, &fbo);
36 }
37 }
39 bool Renderer::init(int xsz, int ysz)
40 {
41 width = xsz;
42 height = ysz;
44 if(!create_rtarg()) {
45 return false;
46 }
48 if(!(post_sdr = load_sdr("post.v.glsl", "post.p.glsl"))) {
49 return false;
50 }
52 if(!gradepal.create()) {
53 return false;
54 }
56 rend = this;
57 return true;
58 }
60 int Renderer::get_tangent_location() const
61 {
62 return -1;
63 }
65 unsigned int Renderer::get_current_program() const
66 {
67 return 0;
68 }
70 void Renderer::resize(int xsz, int ysz)
71 {
72 width = xsz;
73 height = ysz;
75 // if we need a bigger rendertarget ...
76 if(xsz > tex_xsz || ysz > tex_ysz) {
77 tex_xsz = round_pow2(xsz);
78 tex_ysz = round_pow2(ysz);
80 // ... resize the render target
81 glBindTexture(GL_TEXTURE_2D, rend_tex);
82 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_xsz, tex_ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
84 // ... resize the depth buffer
85 glBindRenderbufferEXT(GL_RENDERBUFFER, rend_depth);
86 glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
87 }
88 }
90 void Renderer::render_pre(const Level *level) const
91 {
92 glEnable(GL_FOG);
93 glFogi(GL_FOG_MODE, GL_LINEAR);
94 glFogf(GL_FOG_START, 3.0f);
95 glFogf(GL_FOG_END, 6.0f);
96 // TODO level->draw_pre();
98 // bind the render target
99 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
100 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rend_tex, 0);
101 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
103 CHECKGLERR;
104 }
106 void Renderer::render_post(const Level *level) const
107 {
108 level->draw_post();
109 CHECKGLERR;
111 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
113 // draw the rendered output
114 glActiveTextureARB(GL_TEXTURE0);
115 glBindTexture(GL_TEXTURE_2D, rend_tex);
116 glEnable(GL_TEXTURE_2D);
118 // use the color-grading palette
119 glActiveTextureARB(GL_TEXTURE1);
120 glBindTexture(GL_TEXTURE_3D, gradepal.get_texture());
121 glEnable(GL_TEXTURE_3D);
123 glUseProgram(post_sdr);
124 set_uniform_int(post_sdr, "fbtex", 0);
125 set_uniform_int(post_sdr, "paltex", 1);
127 glBegin(GL_QUADS);
128 glTexCoord2f(0, 0);
129 glVertex2f(-1, -1);
130 glTexCoord2f((float)width / tex_xsz, 0);
131 glVertex2f(1, -1);
132 glTexCoord2f((float)width / tex_xsz, (float)height / tex_ysz);
133 glVertex2f(1, 1);
134 glTexCoord2f(0, (float)height / tex_ysz);
135 glVertex2f(-1, 1);
136 glEnd();
137 glUseProgram(0);
139 glActiveTextureARB(GL_TEXTURE1);
140 glDisable(GL_TEXTURE_3D);
141 glActiveTextureARB(GL_TEXTURE0);
142 glDisable(GL_TEXTURE_2D);
144 CHECKGLERR;
145 }
147 static const char *fbstname[] = {
148 "GL_FRAMEBUFFER_COMPLETE",
149 "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
150 "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
151 "no such fbo error",
152 "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
153 "GL_FRAMEBUFFER_INCOMPLETE_FORMATS",
154 "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER",
155 "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER",
156 "GL_FRAMEBUFFER_UNSUPPORTED"
157 };
159 bool Renderer::create_rtarg()
160 {
161 unsigned int clamp = GLEW_ARB_texture_border_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP;
163 tex_xsz = round_pow2(width);
164 tex_ysz = round_pow2(height);
166 if(!glGenFramebuffersEXT) {
167 fprintf(stderr, "FBO support missing!\n");
168 return false;
169 }
170 glGenFramebuffersEXT(1, &fbo);
171 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
173 // create the render target
174 glGenTextures(1, &rend_tex);
175 glBindTexture(GL_TEXTURE_2D, rend_tex);
176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
177 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
178 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
179 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
180 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_xsz, tex_ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
182 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rend_tex, 0);
184 // create depth buffer
185 glGenRenderbuffersEXT(1, &rend_depth);
186 glBindRenderbufferEXT(GL_RENDERBUFFER, rend_depth);
187 glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
189 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rend_depth);
191 int fbst = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
192 if(fbst != GL_FRAMEBUFFER_COMPLETE) {
193 fprintf(stderr, "incomplete fbo: %u (%s)\n", fbo, fbstname[fbst - GL_FRAMEBUFFER_COMPLETE]);
194 return false;
195 }
196 CHECKGLERR;
198 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
199 return true;
200 }
202 GradePalette *Renderer::get_grade_palette()
203 {
204 return &gradepal;
205 }
207 const GradePalette *Renderer::get_grade_palette() const
208 {
209 return &gradepal;
210 }
213 // ---- fallback forward renderer ----
214 FwdRenderer::FwdRenderer()
215 {
216 sdrprog = 0;
217 tang_attr = -1;
218 }
220 FwdRenderer::~FwdRenderer()
221 {
222 if(sdrprog) {
223 free_program(sdrprog);
224 }
225 }
227 bool FwdRenderer::init(int xsz, int ysz)
228 {
229 if(!Renderer::init(xsz, ysz)) {
230 return false;
231 }
233 if(glUseProgram && (sdrprog = load_sdr("fallback.v.glsl", "fallback.p.glsl"))) {
234 tang_attr = get_attrib_loc(sdrprog, "attr_tangent");
235 set_uniform_int(sdrprog, "tex_dif", 0);
236 set_uniform_int(sdrprog, "tex_norm", 1);
237 }
238 return true;
239 }
241 int FwdRenderer::get_tangent_location() const
242 {
243 return tang_attr;
244 }
246 unsigned int FwdRenderer::get_current_program() const
247 {
248 return sdrprog;
249 }
251 void FwdRenderer::render(const Level *level) const
252 {
253 glPushAttrib(GL_ENABLE_BIT);
254 glEnable(GL_LIGHTING);
256 render_pre(level);
258 glUseProgram(sdrprog);
259 level->draw();
260 glUseProgram(0);
262 render_post(level);
264 glPopAttrib();
265 }
267 static unsigned int load_sdr(const char *vfname, const char *pfname)
268 {
269 unsigned int prog;
271 std::string vsfile = datafile_path(vfname);
272 std::string psfile = datafile_path(pfname);
274 const char *vs = vsfile.empty() ? 0 : vsfile.c_str();
275 const char *ps = psfile.empty() ? 0 : psfile.c_str();
277 if(!(prog = create_program_load(vs, ps))) {
278 fprintf(stderr, "failed to load shader program (%s, %s)\n", vs, ps);
279 return 0;
280 }
281 return prog;
282 }
284 static int round_pow2(int x)
285 {
286 x--;
287 x = (x >> 1) | x;
288 x = (x >> 2) | x;
289 x = (x >> 4) | x;
290 x = (x >> 8) | x;
291 x = (x >> 16) | x;
292 return x + 1;
293 }