dungeon_crawler

changeset 18:5c41e6fcb300

- commandline arguments - stereoscopic rendering - FBO fixed
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 21 Aug 2012 03:17:48 +0300
parents d98240a13793
children 8a0ae6b4aa9b
files prototype/sdr/deferred.p.glsl prototype/sdr/deferred.v.glsl prototype/sdr/mrt.v.glsl prototype/src/camera.cc prototype/src/cfg.cc prototype/src/cfg.h prototype/src/main.cc prototype/src/opengl.cc prototype/src/opengl.h prototype/src/renderer.cc
diffstat 10 files changed, 291 insertions(+), 78 deletions(-) [+]
line diff
     1.1 --- a/prototype/sdr/deferred.p.glsl	Mon Aug 20 06:11:58 2012 +0300
     1.2 +++ b/prototype/sdr/deferred.p.glsl	Tue Aug 21 03:17:48 2012 +0300
     1.3 @@ -1,4 +1,8 @@
     1.4 +uniform sampler2D mrt0;
     1.5 +uniform vec2 tex_scale;
     1.6 +
     1.7  void main()
     1.8  {
     1.9 -	gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    1.10 +	vec4 texel0 = texture2D(mrt0, gl_TexCoord[0].st * tex_scale);
    1.11 +	gl_FragColor = texel0;
    1.12  }
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/prototype/sdr/deferred.v.glsl	Tue Aug 21 03:17:48 2012 +0300
     2.3 @@ -0,0 +1,5 @@
     2.4 +void main()
     2.5 +{
     2.6 +	gl_Position = gl_Vertex;
     2.7 +	gl_TexCoord[0] = gl_MultiTexCoord0;
     2.8 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/prototype/sdr/mrt.v.glsl	Tue Aug 21 03:17:48 2012 +0300
     3.3 @@ -0,0 +1,5 @@
     3.4 +void main()
     3.5 +{
     3.6 +	gl_Position = ftransform();
     3.7 +	gl_TexCoord[0] = gl_MultiTexCoord0;
     3.8 +}
     4.1 --- a/prototype/src/camera.cc	Mon Aug 20 06:11:58 2012 +0300
     4.2 +++ b/prototype/src/camera.cc	Tue Aug 21 03:17:48 2012 +0300
     4.3 @@ -15,25 +15,6 @@
     4.4  	*mat = matrix().inverse();
     4.5  }
     4.6  
     4.7 -void Camera::set_glmat(const Matrix4x4 &mat) const
     4.8 -{
     4.9 -#ifdef SINGLE_PRECISION_MATH
    4.10 -	if(glLoadTransposeMatrixfARB) {
    4.11 -		glLoadTransposeMatrixfARB((float*)&mat);
    4.12 -	} else {
    4.13 -		Matrix4x4 tmat = mat.transposed();
    4.14 -		glLoadMatrixf((float*)&tmat);
    4.15 -	}
    4.16 -#else
    4.17 -	if(glLoadTransposeMatrixdARB) {
    4.18 -		glLoadTransposeMatrixdARB((double*)&mat);
    4.19 -	} else {
    4.20 -		Matrix4x4 tmat = mat.transposed();
    4.21 -		glLoadMatrixd((double*)&tmat);
    4.22 -	}
    4.23 -#endif
    4.24 -}
    4.25 -
    4.26  const Matrix4x4 &Camera::matrix() const
    4.27  {
    4.28  	if(!mcache.valid) {
    4.29 @@ -54,12 +35,12 @@
    4.30  
    4.31  void Camera::use() const
    4.32  {
    4.33 -	set_glmat(matrix());
    4.34 +	mult_matrix(matrix());
    4.35  }
    4.36  
    4.37  void Camera::use_inverse() const
    4.38  {
    4.39 -	set_glmat(inv_matrix());
    4.40 +	mult_matrix(inv_matrix());
    4.41  }
    4.42  
    4.43  void Camera::input_move(float x, float y, float z)
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/prototype/src/cfg.cc	Tue Aug 21 03:17:48 2012 +0300
     5.3 @@ -0,0 +1,46 @@
     5.4 +#include <stdio.h>
     5.5 +#include <stdlib.h>
     5.6 +#include <string.h>
     5.7 +#include "cfg.h"
     5.8 +
     5.9 +Config cfg;
    5.10 +
    5.11 +Config::Config()
    5.12 +{
    5.13 +	width = 800;
    5.14 +	height = 600;
    5.15 +	stereo = false;
    5.16 +	level_file = "0.level";
    5.17 +	tileset_file = "default.tileset";
    5.18 +}
    5.19 +
    5.20 +bool Config::parse_args(int argc, char **argv)
    5.21 +{
    5.22 +	for(int i=1; i<argc; i++) {
    5.23 +		if(strcmp(argv[i], "-s") == 0) {
    5.24 +			if(sscanf(argv[++i], "%dx%d", &width, &height) != 2) {
    5.25 +				fprintf(stderr, "-s must be followed by <width>x<height>\n");
    5.26 +				return false;
    5.27 +			}
    5.28 +		} else if(strcmp(argv[i], "-stereo") == 0) {
    5.29 +			stereo = true;
    5.30 +		} else if(strcmp(argv[i], "-level") == 0) {
    5.31 +			level_file = argv[++i];
    5.32 +		} else if(strcmp(argv[i], "-tileset") == 0) {
    5.33 +			tileset_file = argv[++i];
    5.34 +		} else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
    5.35 +			printf("Usage: %s [options]\n", argv[0]);
    5.36 +			printf("  -s WxH              window size (resolution)\n");
    5.37 +			printf("  -level <filename>   specify which level file to load\n");
    5.38 +			printf("  -tileset <filename> specify which tileset to use\n");
    5.39 +			printf("  -stereo             enable stereoscopic rendering\n");
    5.40 +			printf("  -h/-help            print usage information and exit\n");
    5.41 +			exit(0);
    5.42 +
    5.43 +		} else {
    5.44 +			fprintf(stderr, "unrecognized argument: %s\n", argv[i]);
    5.45 +			return false;
    5.46 +		}
    5.47 +	}
    5.48 +	return true;
    5.49 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/prototype/src/cfg.h	Tue Aug 21 03:17:48 2012 +0300
     6.3 @@ -0,0 +1,15 @@
     6.4 +#ifndef CFG_H_
     6.5 +#define CFG_H_
     6.6 +
     6.7 +extern class Config {
     6.8 +public:
     6.9 +	int width, height;
    6.10 +	bool stereo;
    6.11 +	const char *level_file, *tileset_file;
    6.12 +
    6.13 +	Config();
    6.14 +
    6.15 +	bool parse_args(int argc, char **argv);
    6.16 +} cfg;
    6.17 +
    6.18 +#endif	// CFG_H_
     7.1 --- a/prototype/src/main.cc	Mon Aug 20 06:11:58 2012 +0300
     7.2 +++ b/prototype/src/main.cc	Tue Aug 21 03:17:48 2012 +0300
     7.3 @@ -8,12 +8,15 @@
     7.4  #include "datapath.h"
     7.5  #include "tileset.h"
     7.6  #include "renderer.h"
     7.7 +#include "cfg.h"
     7.8  
     7.9  bool init(int xsz, int ysz);
    7.10  void cleanup();
    7.11  void idle();
    7.12  void disp();
    7.13  void draw();
    7.14 +void view_matrix(int eye);
    7.15 +void proj_matrix(int eye);
    7.16  void update(unsigned long msec);
    7.17  void reshape(int x, int y);
    7.18  void keyb(unsigned char key, int x, int y);
    7.19 @@ -27,23 +30,21 @@
    7.20  static FpsCamera cam;
    7.21  static bool keystate[256];
    7.22  
    7.23 -static const char *level_file = "0.level";
    7.24 +static float stereo_focus_dist = 0.25;
    7.25 +static float stereo_eye_sep = stereo_focus_dist / 30.0;
    7.26 +
    7.27  
    7.28  int main(int argc, char **argv)
    7.29  {
    7.30 -	int xsz, ysz;
    7.31 -
    7.32  	glutInit(&argc, argv);
    7.33  
    7.34 -	if(argc > 1) {
    7.35 -		level_file = argv[1];
    7.36 +	if(!cfg.parse_args(argc, argv)) {
    7.37 +		return 1;
    7.38  	}
    7.39  
    7.40 -	glutInitWindowSize(800, 600);
    7.41 -	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE);
    7.42 -	glutCreateWindow("prototype");
    7.43 -	xsz = glutGet(GLUT_WINDOW_WIDTH);
    7.44 -	ysz = glutGet(GLUT_WINDOW_HEIGHT);
    7.45 +	glutInitWindowSize(cfg.width, cfg.height);
    7.46 +	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (cfg.stereo ? GLUT_STEREO : 0));
    7.47 +	glutCreateWindow("dungeon crawler prototype");
    7.48  
    7.49  	glutIdleFunc(idle);
    7.50  	glutDisplayFunc(disp);
    7.51 @@ -55,7 +56,7 @@
    7.52  
    7.53  	glewInit();
    7.54  
    7.55 -	if(!init(xsz, ysz)) {
    7.56 +	if(!init(cfg.width, cfg.height)) {
    7.57  		return 1;
    7.58  	}
    7.59  
    7.60 @@ -83,14 +84,15 @@
    7.61  
    7.62  	// load a tileset
    7.63  	tileset = new TileSet;
    7.64 -	if(!tileset->load(datafile_path("default.tileset"))) {
    7.65 +	printf("loading tileset: %s\n", cfg.tileset_file);
    7.66 +	if(!tileset->load(datafile_path(cfg.tileset_file))) {
    7.67  		return false;
    7.68  	}
    7.69  	set_active_tileset(tileset);
    7.70  
    7.71  	level = new Level;
    7.72 -	printf("loading level: %s\n", level_file);
    7.73 -	if(!level->load(datafile_path(level_file))) {
    7.74 +	printf("loading level: %s\n", cfg.level_file);
    7.75 +	if(!level->load(datafile_path(cfg.level_file))) {
    7.76  		return false;
    7.77  	}
    7.78  
    7.79 @@ -116,13 +118,39 @@
    7.80  {
    7.81  	update(glutGet(GLUT_ELAPSED_TIME));
    7.82  
    7.83 -	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    7.84 +	if(cfg.stereo) {
    7.85 +		glDrawBuffer(GL_BACK_LEFT);
    7.86  
    7.87 -	glMatrixMode(GL_MODELVIEW);
    7.88 -	glLoadIdentity();
    7.89 -	cam.use_inverse();
    7.90 +		glMatrixMode(GL_PROJECTION);
    7.91 +		glLoadIdentity();
    7.92 +		proj_matrix(-1);
    7.93 +		glMatrixMode(GL_MODELVIEW);
    7.94 +		glLoadIdentity();
    7.95 +		view_matrix(-1);
    7.96  
    7.97 -	render_deferred(draw);
    7.98 +		render_deferred(draw);
    7.99 +
   7.100 +		glDrawBuffer(GL_BACK_RIGHT);
   7.101 +
   7.102 +		glMatrixMode(GL_PROJECTION);
   7.103 +		glLoadIdentity();
   7.104 +		proj_matrix(1);
   7.105 +		glMatrixMode(GL_MODELVIEW);
   7.106 +		glLoadIdentity();
   7.107 +		view_matrix(1);
   7.108 +
   7.109 +		render_deferred(draw);
   7.110 +
   7.111 +	} else {
   7.112 +		glMatrixMode(GL_PROJECTION);
   7.113 +		glLoadIdentity();
   7.114 +		proj_matrix(0);
   7.115 +		glMatrixMode(GL_MODELVIEW);
   7.116 +		glLoadIdentity();
   7.117 +		view_matrix(0);
   7.118 +
   7.119 +		render_deferred(draw);
   7.120 +	}
   7.121  
   7.122  	glutSwapBuffers();
   7.123  	assert(glGetError() == GL_NO_ERROR);
   7.124 @@ -132,9 +160,31 @@
   7.125  
   7.126  void draw()
   7.127  {
   7.128 +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   7.129  	level->draw();
   7.130  }
   7.131  
   7.132 +void view_matrix(int eye)
   7.133 +{
   7.134 +	float offs = stereo_eye_sep * eye * 0.5;
   7.135 +	glTranslatef(-offs, 0, 0);
   7.136 +	cam.use_inverse();
   7.137 +}
   7.138 +
   7.139 +void proj_matrix(int eye)
   7.140 +{
   7.141 +	static const float fov = M_PI / 4.0;
   7.142 +	static const float near_clip = 0.1;
   7.143 +	static const float far_clip = 100.0;
   7.144 +
   7.145 +	float top = near_clip * tan(fov * 0.5);
   7.146 +	float right = top * (float)cfg.width / (float)cfg.height;
   7.147 +
   7.148 +	float frust_shift = -(float)eye * (stereo_eye_sep * 0.5 * near_clip / stereo_focus_dist);
   7.149 +	glFrustum(-right + frust_shift, right + frust_shift, -top, top, near_clip, far_clip);
   7.150 +}
   7.151 +
   7.152 +
   7.153  void update(unsigned long msec)
   7.154  {
   7.155  	static unsigned long last_upd;
   7.156 @@ -169,16 +219,39 @@
   7.157  void reshape(int x, int y)
   7.158  {
   7.159  	glViewport(0, 0, x, y);
   7.160 -	glMatrixMode(GL_PROJECTION);
   7.161 -	glLoadIdentity();
   7.162 -	gluPerspective(45.0, (float)x / (float)y, 0.25, 100.0);
   7.163 +	cfg.width = x;
   7.164 +	cfg.height = y;
   7.165  }
   7.166  
   7.167 +static bool stereo_shift_pressed;
   7.168 +
   7.169  void keyb(unsigned char key, int x, int y)
   7.170  {
   7.171  	switch(key) {
   7.172  	case 27:
   7.173  		exit(0);
   7.174 +
   7.175 +	case 'z':
   7.176 +		stereo_shift_pressed = true;
   7.177 +		break;
   7.178 +
   7.179 +	case '\n':
   7.180 +	case '\r':
   7.181 +		{
   7.182 +			static bool fullscr;
   7.183 +			if(glutGetModifiers() & GLUT_ACTIVE_ALT) {
   7.184 +				fullscr = !fullscr;
   7.185 +				if(fullscr) {
   7.186 +					glutFullScreen();
   7.187 +				} else {
   7.188 +					glutPositionWindow(20, 20);
   7.189 +				}
   7.190 +			}
   7.191 +		}
   7.192 +		break;
   7.193 +
   7.194 +	default:
   7.195 +		break;
   7.196  	}
   7.197  
   7.198  	keystate[key] = true;
   7.199 @@ -186,6 +259,15 @@
   7.200  
   7.201  void key_release(unsigned char key, int x, int y)
   7.202  {
   7.203 +	switch(key) {
   7.204 +	case 'z':
   7.205 +		stereo_shift_pressed = false;
   7.206 +		break;
   7.207 +
   7.208 +	default:
   7.209 +		break;
   7.210 +	}
   7.211 +
   7.212  	keystate[key] = false;
   7.213  }
   7.214  
   7.215 @@ -206,6 +288,16 @@
   7.216  	prev_x = x;
   7.217  	prev_y = y;
   7.218  
   7.219 +	if(stereo_shift_pressed) {
   7.220 +		if(dy != 0) {
   7.221 +			stereo_focus_dist += dy * 0.01;
   7.222 +			stereo_eye_sep = stereo_focus_dist / 30.0;
   7.223 +			printf("foc: %f, sep: %f\n", stereo_focus_dist, stereo_eye_sep);
   7.224 +			glutPostRedisplay();
   7.225 +		}
   7.226 +		return;
   7.227 +	}
   7.228 +
   7.229  	if(bnstate[0]) {
   7.230  		cam.input_rotate(dy * 0.01, dx * 0.01, 0);
   7.231  		glutPostRedisplay();
     8.1 --- a/prototype/src/opengl.cc	Mon Aug 20 06:11:58 2012 +0300
     8.2 +++ b/prototype/src/opengl.cc	Tue Aug 21 03:17:48 2012 +0300
     8.3 @@ -38,3 +38,24 @@
     8.4  	}
     8.5  #endif
     8.6  }
     8.7 +
     8.8 +const char *strglerr(int err)
     8.9 +{
    8.10 +	static const char *errnames[] = {
    8.11 +		"GL_INVALID_ENUM",
    8.12 +		"GL_INVALID_VALUE",
    8.13 +		"GL_INVALID_OPERATION",
    8.14 +		"GL_STACK_OVERFLOW",
    8.15 +		"GL_STACK_UNDERFLOW",
    8.16 +		"GL_OUT_OF_MEMORY",
    8.17 +		"GL_INVALID_FRAMEBUFFER_OPERATION"
    8.18 +	};
    8.19 +
    8.20 +	if(!err) {
    8.21 +		return "GL_NO_ERROR";
    8.22 +	}
    8.23 +	if(err < GL_INVALID_ENUM || err > GL_OUT_OF_MEMORY) {
    8.24 +		return "<invalid gl error>";
    8.25 +	}
    8.26 +	return errnames[err - GL_INVALID_ENUM];
    8.27 +}
     9.1 --- a/prototype/src/opengl.h	Mon Aug 20 06:11:58 2012 +0300
     9.2 +++ b/prototype/src/opengl.h	Tue Aug 21 03:17:48 2012 +0300
     9.3 @@ -9,9 +9,21 @@
     9.4  #include <GLUT/glut.h>
     9.5  #endif
     9.6  
     9.7 +#define CHECKGLERR	\
     9.8 +	do { \
     9.9 +		int err = glGetError(); \
    9.10 +		if(err) { \
    9.11 +			fprintf(stderr, "%s:%d: OpenGL error 0x%x: %s\n", __FILE__, __LINE__, err, strglerr(err)); \
    9.12 +			abort(); \
    9.13 +		} \
    9.14 +	} while(0)
    9.15 +
    9.16 +
    9.17  class Matrix4x4;
    9.18  
    9.19  void load_matrix(const Matrix4x4 &m);
    9.20  void mult_matrix(const Matrix4x4 &m);
    9.21  
    9.22 +const char *strglerr(int err);
    9.23 +
    9.24  #endif	/* OPENGL_H_ */
    10.1 --- a/prototype/src/renderer.cc	Mon Aug 20 06:11:58 2012 +0300
    10.2 +++ b/prototype/src/renderer.cc	Tue Aug 21 03:17:48 2012 +0300
    10.3 @@ -2,21 +2,23 @@
    10.4  #include <stdlib.h>
    10.5  #include <string.h>
    10.6  #include <limits.h>
    10.7 +#include <assert.h>
    10.8  #include "opengl.h"
    10.9  #include "renderer.h"
   10.10  #include "sdr.h"
   10.11  #include "datapath.h"
   10.12  
   10.13 +
   10.14  static bool create_fbo(int xsz, int ysz);
   10.15 -static bool load_shaders();
   10.16 +static unsigned int load_sdr(const char *vfname, const char *pfname);
   10.17  static int round_pow2(int x);
   10.18  
   10.19  
   10.20 -#define MRT_COUNT	4
   10.21 +#define MRT_COUNT	1
   10.22  static unsigned int mrt_tex[MRT_COUNT];
   10.23  
   10.24  static unsigned int mrt_prog;
   10.25 -static unsigned int deferred_omni;
   10.26 +static unsigned int deferred_omni, deferred_debug;
   10.27  
   10.28  static unsigned int fbo, rbuf_depth;
   10.29  static const char *fbstname[] = {
   10.30 @@ -38,7 +40,11 @@
   10.31  	if(!create_fbo(xsz, ysz)) {
   10.32  		return false;
   10.33  	}
   10.34 -	if(!load_shaders()) {
   10.35 +
   10.36 +	if(!(mrt_prog = load_sdr("mrt.v.glsl", "mrt.p.glsl"))) {
   10.37 +		return false;
   10.38 +	}
   10.39 +	if(!(deferred_debug = load_sdr("deferred.v.glsl", "deferred.p.glsl"))) {
   10.40  		return false;
   10.41  	}
   10.42  	return true;
   10.43 @@ -55,9 +61,45 @@
   10.44  
   10.45  void render_deferred(void (*draw_func)())
   10.46  {
   10.47 -	bind_program(mrt_prog);
   10.48 +	int loc;
   10.49 +
   10.50 +	// render into the MRT buffers
   10.51 +	glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
   10.52 +	glUseProgram(mrt_prog);
   10.53  	draw_func();
   10.54 -	bind_program(0);
   10.55 +	glUseProgram(0);
   10.56 +	glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
   10.57 +
   10.58 +
   10.59 +	// post-process lighting
   10.60 +	glPushAttrib(GL_ENABLE_BIT);
   10.61 +
   10.62 +	glDisable(GL_LIGHTING);
   10.63 +	glDisable(GL_DEPTH_TEST);
   10.64 +	glBindTexture(GL_TEXTURE_2D, mrt_tex[0]);
   10.65 +	glEnable(GL_TEXTURE_2D);
   10.66 +
   10.67 +	glUseProgram(deferred_debug);
   10.68 +	if((loc = glGetUniformLocation(deferred_debug, "tex0")) != -1) {
   10.69 +		glUniform1i(loc, 0);
   10.70 +	}
   10.71 +	if((loc = glGetUniformLocation(deferred_debug, "tex_scale")) != -1) {
   10.72 +		glUniform2f(loc, (float)fb_xsz / tex_xsz, (float)fb_ysz / tex_ysz);
   10.73 +	}
   10.74 +
   10.75 +	glBegin(GL_QUADS);
   10.76 +	glTexCoord2f(0, 0);
   10.77 +	glVertex2f(-1, -1);
   10.78 +	glTexCoord2f(1, 0);
   10.79 +	glVertex2f(1, -1);
   10.80 +	glTexCoord2f(1, 1);
   10.81 +	glVertex2f(1, 1);
   10.82 +	glTexCoord2f(0, 1);
   10.83 +	glVertex2f(-1, 1);
   10.84 +	glEnd();
   10.85 +
   10.86 +	glUseProgram(0);
   10.87 +	glPopAttrib();
   10.88  }
   10.89  
   10.90  static bool create_fbo(int xsz, int ysz)
   10.91 @@ -74,11 +116,7 @@
   10.92  		return false;
   10.93  	}
   10.94  	glGenFramebuffersEXT(1, &fbo);
   10.95 -
   10.96 -	glGenRenderbuffersEXT(1, &rbuf_depth);
   10.97 -	glBindRenderbufferEXT(GL_RENDERBUFFER, rbuf_depth);
   10.98 -	glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
   10.99 -	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_depth);
  10.100 +	glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
  10.101  
  10.102  	glGenTextures(MRT_COUNT, mrt_tex);
  10.103  	for(int i=0; i<MRT_COUNT; i++) {
  10.104 @@ -92,52 +130,46 @@
  10.105  		// attach to fbo
  10.106  		glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
  10.107  				mrt_tex[i], 0);
  10.108 +		CHECKGLERR;
  10.109  	}
  10.110  
  10.111 +	glGenRenderbuffersEXT(1, &rbuf_depth);
  10.112 +	glBindRenderbufferEXT(GL_RENDERBUFFER, rbuf_depth);
  10.113 +	glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
  10.114 +	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_depth);
  10.115 +
  10.116  	int fbst = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
  10.117  	if(fbst != GL_FRAMEBUFFER_COMPLETE) {
  10.118  		fprintf(stderr, "incomplete fbo: %u (%s)\n", fbo, fbstname[fbst - GL_FRAMEBUFFER_COMPLETE]);
  10.119  		return false;
  10.120  	}
  10.121 +	CHECKGLERR;
  10.122 +
  10.123 +	glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
  10.124  	return true;
  10.125  }
  10.126  
  10.127 -static bool load_shaders()
  10.128 +static unsigned int load_sdr(const char *vfname, const char *pfname)
  10.129  {
  10.130  	char vsfile[PATH_MAX], psfile[PATH_MAX];
  10.131  	const char *fname;
  10.132 +	unsigned int prog;
  10.133  
  10.134 -	if((fname = datafile_path("mrt.v.glsl"))) {
  10.135 +	if((fname = datafile_path(vfname))) {
  10.136  		strcpy(vsfile, fname);
  10.137  	} else {
  10.138  		vsfile[0] = 0;
  10.139  	}
  10.140 -	if((fname = datafile_path("mrt.p.glsl"))) {
  10.141 +	if((fname = datafile_path(pfname))) {
  10.142  		strcpy(psfile, fname);
  10.143  	} else {
  10.144  		psfile[0] = 0;
  10.145  	}
  10.146 -	if(!(mrt_prog = create_program_load(vsfile, psfile))) {
  10.147 -		fprintf(stderr, "failed to load MRT program\n");
  10.148 -		return false;
  10.149 +	if(!(prog = create_program_load(vsfile, psfile))) {
  10.150 +		fprintf(stderr, "failed to load shader program (%s, %s)\n", vsfile, psfile);
  10.151 +		return 0;
  10.152  	}
  10.153 -
  10.154 -	if((fname = datafile_path("deferred.v.glsl"))) {
  10.155 -		strcpy(vsfile, fname);
  10.156 -	} else {
  10.157 -		vsfile[0] = 0;
  10.158 -	}
  10.159 -	if((fname = datafile_path("deferred.p.glsl"))) {
  10.160 -		strcpy(psfile, fname);
  10.161 -	} else {
  10.162 -		psfile[0] = 0;
  10.163 -	}
  10.164 -
  10.165 -	if(!(deferred_omni = create_program_load(vsfile, psfile))) {
  10.166 -		fprintf(stderr, "failed to load deferred shader program\n");
  10.167 -		return false;
  10.168 -	}
  10.169 -	return true;
  10.170 +	return prog;
  10.171  }
  10.172  
  10.173  static int round_pow2(int x)