dungeon_crawler

view prototype/src/renderer_deferred.cc @ 41:acfe0c0110fc

- cleaned up the renderer - implemented fallback (non-deferred renderer)
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 30 Aug 2012 05:35:00 +0300
parents
children aa86119e3295
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <limits.h>
5 #include "opengl.h"
6 #include "renderer_deferred.h"
7 #include "level.h"
8 #include "sdr.h"
9 #include "datapath.h"
11 static unsigned int load_sdr(const char *vfname, const char *pfname);
12 static int round_pow2(int x);
14 DeferredRenderer::DeferredRenderer()
15 {
16 fbo = rbuf_depth = 0;
17 for(int i=0; i<MRT_COUNT; i++) {
18 mrt_tex[i] = 0;
19 }
20 tex_xsz = tex_ysz = 0;
22 mrt_prog = deferred_debug = deferred_omni = 0;
24 curr_prog = 0;
25 }
27 DeferredRenderer::~DeferredRenderer()
28 {
29 if(mrt_prog) {
30 free_program(mrt_prog);
31 }
32 if(deferred_omni) {
33 free_program(deferred_omni);
34 }
35 if(deferred_debug) {
36 free_program(deferred_debug);
37 }
39 if(mrt_tex[0]) {
40 glDeleteTextures(MRT_COUNT, mrt_tex);
41 }
42 if(fbo) {
43 glDeleteFramebuffersEXT(1, &fbo);
44 }
45 }
47 bool DeferredRenderer::init(int xsz, int ysz)
48 {
49 width = xsz;
50 height = ysz;
52 if(!GLEW_ARB_texture_float) {
53 fprintf(stderr, "%s: error: no floating point texture support\n", __func__);
54 return false;
55 }
56 if(!GLEW_ARB_draw_buffers) {
57 fprintf(stderr, "%s: error: no multiple render target support\n", __func__);
58 return false;
59 }
61 int max_draw_buf;
62 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buf);
63 printf("max draw buffers: %d\n", max_draw_buf);
64 if(max_draw_buf < MRT_COUNT) {
65 fprintf(stderr, "%s: error: not enough draw buffers (%d), %d required\n", __func__, max_draw_buf, MRT_COUNT);
66 return false;
67 }
69 if(!create_fbo()) {
70 return false;
71 }
73 if(!(mrt_prog = load_sdr("mrt.v.glsl", "mrt.p.glsl"))) {
74 return false;
75 }
76 set_uniform_int(mrt_prog, "tex_dif", 0);
77 set_uniform_int(mrt_prog, "tex_norm", 1);
79 if(!(deferred_omni = load_sdr("deferred_omni.v.glsl", "deferred_omni.p.glsl"))) {
80 return false;
81 }
82 for(int i=0; i<MRT_COUNT; i++) {
83 char uname[32];
84 sprintf(uname, "mrt%d", i);
85 set_uniform_int(deferred_omni, uname, i);
86 }
88 rend = this;
89 return true;
90 }
92 int DeferredRenderer::get_tangent_location() const
93 {
94 return get_attrib_loc(mrt_prog, "attr_tangent");
95 }
97 unsigned int DeferredRenderer::get_current_program() const
98 {
99 return curr_prog;
100 }
102 void DeferredRenderer::resize(int xsz, int ysz)
103 {
104 width = xsz;
105 height = ysz;
107 // if we need a bigger rendertarget ...
108 if(xsz > tex_xsz || ysz > tex_ysz) {
109 tex_xsz = round_pow2(xsz);
110 tex_ysz = round_pow2(ysz);
112 // ... resize all the color buffers
113 for(int i=0; i<MRT_COUNT; i++) {
114 glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
115 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, tex_xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, 0);
116 }
118 // ... resize the depth buffer
119 glBindRenderbufferEXT(GL_RENDERBUFFER, rbuf_depth);
120 glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
121 }
123 // update the texture coordinate scaling factors
124 float tex_scale_x = (float)width / tex_xsz;
125 float tex_scale_y = (float)height / tex_ysz;
127 set_uniform_float2(deferred_omni, "tex_scale", tex_scale_x, tex_scale_y);
128 set_uniform_float2(deferred_omni, "fb_size", width, height);
129 }
131 void DeferredRenderer::render(const Level *level) const
132 {
133 // render into the MRT buffers
134 glUseProgram(mrt_prog);
135 curr_prog = mrt_prog;
137 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
139 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
140 level->draw();
142 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
144 // post-process lighting
145 glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
147 glEnable(GL_BLEND);
148 glBlendFunc(GL_ONE, GL_ONE);
150 glDisable(GL_LIGHTING);
151 glDisable(GL_DEPTH_TEST);
152 glCullFace(GL_FRONT);
154 glUseProgram(deferred_omni);
155 curr_prog = deferred_omni;
157 for(int i=0; i<MRT_COUNT; i++) {
158 glActiveTexture(GL_TEXTURE0 + i);
159 glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
160 glEnable(GL_TEXTURE_2D);
161 }
163 glDepthMask(0);
164 level->draw_lights();
165 glDepthMask(1);
167 for(int i=0; i<MRT_COUNT; i++) {
168 glActiveTexture(GL_TEXTURE0 + MRT_COUNT - i - 1);
169 glDisable(GL_TEXTURE_2D);
170 }
172 glUseProgram(0);
173 curr_prog = 0;
174 glPopAttrib();
175 }
177 static const char *fbstname[] = {
178 "GL_FRAMEBUFFER_COMPLETE",
179 "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
180 "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
181 "no such fbo error",
182 "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
183 "GL_FRAMEBUFFER_INCOMPLETE_FORMATS",
184 "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER",
185 "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER",
186 "GL_FRAMEBUFFER_UNSUPPORTED"
187 };
189 bool DeferredRenderer::create_fbo()
190 {
191 unsigned int clamp = GLEW_ARB_texture_border_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP;
193 // round the texture size up to the next power of 2
194 tex_xsz = round_pow2(width);
195 tex_ysz = round_pow2(height);
197 if(!glGenFramebuffersEXT) {
198 fprintf(stderr, "FBO support missing\n");
199 return false;
200 }
201 glGenFramebuffersEXT(1, &fbo);
202 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
204 glGenTextures(MRT_COUNT, mrt_tex);
205 for(int i=0; i<MRT_COUNT; i++) {
206 glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
207 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
211 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, tex_xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, 0);
213 // attach to fbo
214 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
215 GL_TEXTURE_2D, mrt_tex[i], 0);
216 CHECKGLERR;
217 }
219 static GLenum draw_bufs[] = {
220 GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT,
221 GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT,
222 GL_COLOR_ATTACHMENT4_EXT, GL_COLOR_ATTACHMENT5_EXT,
223 GL_COLOR_ATTACHMENT6_EXT, GL_COLOR_ATTACHMENT7_EXT
224 };
225 glDrawBuffersARB(MRT_COUNT, draw_bufs);
227 glGenRenderbuffersEXT(1, &rbuf_depth);
228 glBindRenderbufferEXT(GL_RENDERBUFFER, rbuf_depth);
229 glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
230 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_depth);
232 int fbst = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
233 if(fbst != GL_FRAMEBUFFER_COMPLETE) {
234 fprintf(stderr, "incomplete fbo: %u (%s)\n", fbo, fbstname[fbst - GL_FRAMEBUFFER_COMPLETE]);
235 return false;
236 }
237 CHECKGLERR;
239 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
240 return true;
241 }
243 static unsigned int load_sdr(const char *vfname, const char *pfname)
244 {
245 char vsfile[PATH_MAX], psfile[PATH_MAX];
246 const char *fname;
247 unsigned int prog;
249 if((fname = datafile_path(vfname))) {
250 strcpy(vsfile, fname);
251 } else {
252 vsfile[0] = 0;
253 }
254 if((fname = datafile_path(pfname))) {
255 strcpy(psfile, fname);
256 } else {
257 psfile[0] = 0;
258 }
259 if(!(prog = create_program_load(vsfile, psfile))) {
260 fprintf(stderr, "failed to load shader program (%s, %s)\n", vsfile, psfile);
261 return 0;
262 }
263 return prog;
264 }
266 static int round_pow2(int x)
267 {
268 x--;
269 x = (x >> 1) | x;
270 x = (x >> 2) | x;
271 x = (x >> 4) | x;
272 x = (x >> 8) | x;
273 x = (x >> 16) | x;
274 return x + 1;
275 }
277 #ifdef DBG_VIS_MRT
278 // visualize the MRT buffers
279 static void draw_deferred_debug()
280 {
281 glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
282 glUseProgram(deferred_debug);
283 glDisable(GL_DEPTH_TEST);
285 glMatrixMode(GL_PROJECTION);
286 glPushMatrix();
287 glLoadIdentity();
288 glMatrixMode(GL_MODELVIEW);
289 glPushMatrix();
290 glLoadIdentity();
292 for(int i=0; i<MRT_COUNT; i++) {
293 glActiveTexture(GL_TEXTURE0 + i);
294 glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
295 glEnable(GL_TEXTURE_2D);
296 }
298 glBegin(GL_QUADS);
299 glTexCoord2f(0, 0);
300 glVertex2f(-1, -1);
301 glTexCoord2f(1, 0);
302 glVertex2f(1, -1);
303 glTexCoord2f(1, 1);
304 glVertex2f(1, 1);
305 glTexCoord2f(0, 1);
306 glVertex2f(-1, 1);
307 glEnd();
309 for(int i=0; i<MRT_COUNT; i++) {
310 glActiveTexture(GL_TEXTURE0 + MRT_COUNT - i - 1);
311 glDisable(GL_TEXTURE_2D);
312 }
314 glMatrixMode(GL_PROJECTION);
315 glPopMatrix();
316 glMatrixMode(GL_MODELVIEW);
317 glPopMatrix();
319 glUseProgram(0);
320 glPopAttrib();
321 }
322 #endif