dungeon_crawler

changeset 15:3a3236a4833c

adding shaders and renderer abstraction
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 19 Aug 2012 23:09:30 +0300
parents 67ae9fcb802c
children 91180ee7b7d9
files prototype/src/main.cc prototype/src/renderer.cc prototype/src/renderer.h prototype/src/sdr.c prototype/src/sdr.h
diffstat 5 files changed, 483 insertions(+), 1 deletions(-) [+]
line diff
     1.1 --- a/prototype/src/main.cc	Sun Aug 19 06:30:18 2012 +0300
     1.2 +++ b/prototype/src/main.cc	Sun Aug 19 23:09:30 2012 +0300
     1.3 @@ -7,11 +7,13 @@
     1.4  #include "camera.h"
     1.5  #include "datapath.h"
     1.6  #include "tileset.h"
     1.7 +#include "renderer.h"
     1.8  
     1.9  bool init();
    1.10  void cleanup();
    1.11  void idle();
    1.12  void disp();
    1.13 +void draw();
    1.14  void update(unsigned long msec);
    1.15  void reshape(int x, int y);
    1.16  void keyb(unsigned char key, int x, int y);
    1.17 @@ -70,6 +72,10 @@
    1.18  
    1.19  	add_data_path("data");
    1.20  
    1.21 +	if(!init_renderer()) {
    1.22 +		return false;
    1.23 +	}
    1.24 +
    1.25  	// load a tileset
    1.26  	tileset = new TileSet;
    1.27  	if(!tileset->load(datafile_path("default.tileset"))) {
    1.28 @@ -88,6 +94,14 @@
    1.29  	return true;
    1.30  }
    1.31  
    1.32 +void cleanup()
    1.33 +{
    1.34 +	delete level;
    1.35 +	delete tileset;
    1.36 +
    1.37 +	destroy_renderer();
    1.38 +}
    1.39 +
    1.40  void idle()
    1.41  {
    1.42  	glutPostRedisplay();
    1.43 @@ -103,7 +117,7 @@
    1.44  	glLoadIdentity();
    1.45  	cam.use_inverse();
    1.46  
    1.47 -	level->draw();
    1.48 +	render_deferred(draw);
    1.49  
    1.50  	glutSwapBuffers();
    1.51  	assert(glGetError() == GL_NO_ERROR);
    1.52 @@ -111,6 +125,11 @@
    1.53  	usleep(10000);
    1.54  }
    1.55  
    1.56 +void draw()
    1.57 +{
    1.58 +	level->draw();
    1.59 +}
    1.60 +
    1.61  void update(unsigned long msec)
    1.62  {
    1.63  	static unsigned long last_upd;
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/prototype/src/renderer.cc	Sun Aug 19 23:09:30 2012 +0300
     2.3 @@ -0,0 +1,77 @@
     2.4 +#include <stdio.h>
     2.5 +#include <stdlib.h>
     2.6 +#include <string.h>
     2.7 +#include <limits.h>
     2.8 +#include "opengl.h"
     2.9 +#include "renderer.h"
    2.10 +#include "sdr.h"
    2.11 +#include "datapath.h"
    2.12 +
    2.13 +#define MRT_COUNT	4
    2.14 +
    2.15 +static const char *mrt_sdr_file[][2] = {
    2.16 +	{0, "mrt0.p.glsl"},
    2.17 +	{0, "mrt1.p.glsl"},
    2.18 +	{0, "mrt2.p.glsl"},
    2.19 +	{0, "mrt3.p.glsl"}
    2.20 +};
    2.21 +
    2.22 +static unsigned int mrt_prog[MRT_COUNT];
    2.23 +static unsigned int deferred_prog;
    2.24 +
    2.25 +bool init_renderer()
    2.26 +{
    2.27 +	char vsfile[PATH_MAX], psfile[PATH_MAX];
    2.28 +	const char *fname;
    2.29 +
    2.30 +	for(int i=0; i<MRT_COUNT; i++) {
    2.31 +		if((fname = datafile_path(mrt_sdr_file[i][0]))) {
    2.32 +			strcpy(vsfile, mrt_sdr_file[i][0]);
    2.33 +		} else {
    2.34 +			vsfile[0] = 0;
    2.35 +		}
    2.36 +
    2.37 +		if((fname = datafile_path(mrt_sdr_file[i][1]))) {
    2.38 +			strcpy(psfile, mrt_sdr_file[i][1]);
    2.39 +		} else {
    2.40 +			psfile[0] = 0;
    2.41 +		}
    2.42 +
    2.43 +		if(!(mrt_prog[i] = create_program_load(vsfile, psfile))) {
    2.44 +			fprintf(stderr, "failed to load MRT program\n");
    2.45 +			return false;
    2.46 +		}
    2.47 +	}
    2.48 +
    2.49 +	if((fname = datafile_path("deferred.v.glsl"))) {
    2.50 +		strcpy(vsfile, fname);
    2.51 +	} else {
    2.52 +		vsfile[0] = 0;
    2.53 +	}
    2.54 +	if((fname = datafile_path("deferred.p.glsl"))) {
    2.55 +		strcpy(psfile, fname);
    2.56 +	} else {
    2.57 +		psfile[0] = 0;
    2.58 +	}
    2.59 +
    2.60 +	if(!(deferred_prog = create_program_load(vsfile, psfile))) {
    2.61 +		fprintf(stderr, "failed to load deferred shader program\n");
    2.62 +		return false;
    2.63 +	}
    2.64 +	return true;
    2.65 +}
    2.66 +
    2.67 +void destroy_renderer()
    2.68 +{
    2.69 +	for(int i=0; i<MRT_COUNT; i++) {
    2.70 +		free_program(mrt_prog[i]);
    2.71 +	}
    2.72 +	free_program(deferred_prog);
    2.73 +}
    2.74 +
    2.75 +void render_deferred(void (*draw_func)())
    2.76 +{
    2.77 +
    2.78 +
    2.79 +	draw_func();
    2.80 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/prototype/src/renderer.h	Sun Aug 19 23:09:30 2012 +0300
     3.3 @@ -0,0 +1,9 @@
     3.4 +#ifndef RENDERER_H_
     3.5 +#define RENDERER_H_
     3.6 +
     3.7 +bool init_renderer();
     3.8 +void destroy_renderer();
     3.9 +
    3.10 +void render_deferred(void (*draw_func)());
    3.11 +
    3.12 +#endif	// RENDERER_H_
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/prototype/src/sdr.c	Sun Aug 19 23:09:30 2012 +0300
     4.3 @@ -0,0 +1,328 @@
     4.4 +#include <stdio.h>
     4.5 +#include <stdlib.h>
     4.6 +#include <string.h>
     4.7 +#include <errno.h>
     4.8 +#include <assert.h>
     4.9 +#include <GL/glew.h>
    4.10 +
    4.11 +#if defined(unix) || defined(__unix__)
    4.12 +#include <unistd.h>
    4.13 +#include <sys/stat.h>
    4.14 +#endif	/* unix */
    4.15 +
    4.16 +#include "sdr.h"
    4.17 +
    4.18 +unsigned int create_vertex_shader(const char *src)
    4.19 +{
    4.20 +	return create_shader(src, GL_VERTEX_SHADER);
    4.21 +}
    4.22 +
    4.23 +unsigned int create_pixel_shader(const char *src)
    4.24 +{
    4.25 +	return create_shader(src, GL_FRAGMENT_SHADER);
    4.26 +}
    4.27 +
    4.28 +unsigned int create_shader(const char *src, unsigned int sdr_type)
    4.29 +{
    4.30 +	unsigned int sdr;
    4.31 +	int success, info_len;
    4.32 +	char *info_str = 0;
    4.33 +	GLenum err;
    4.34 +
    4.35 +	sdr = glCreateShader(sdr_type);
    4.36 +	assert(glGetError() == GL_NO_ERROR);
    4.37 +	glShaderSource(sdr, 1, &src, 0);
    4.38 +	err = glGetError();
    4.39 +	assert(err == GL_NO_ERROR);
    4.40 +	glCompileShader(sdr);
    4.41 +	assert(glGetError() == GL_NO_ERROR);
    4.42 +
    4.43 +	glGetShaderiv(sdr, GL_COMPILE_STATUS, &success);
    4.44 +	assert(glGetError() == GL_NO_ERROR);
    4.45 +	glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len);
    4.46 +	assert(glGetError() == GL_NO_ERROR);
    4.47 +
    4.48 +	if(info_len) {
    4.49 +		if((info_str = malloc(info_len + 1))) {
    4.50 +			glGetShaderInfoLog(sdr, info_len, 0, info_str);
    4.51 +			assert(glGetError() == GL_NO_ERROR);
    4.52 +		}
    4.53 +	}
    4.54 +
    4.55 +	if(success) {
    4.56 +		fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str);
    4.57 +	} else {
    4.58 +		fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str);
    4.59 +		glDeleteShader(sdr);
    4.60 +		sdr = 0;
    4.61 +	}
    4.62 +
    4.63 +	free(info_str);
    4.64 +	return sdr;
    4.65 +}
    4.66 +
    4.67 +void free_shader(unsigned int sdr)
    4.68 +{
    4.69 +	glDeleteShader(sdr);
    4.70 +}
    4.71 +
    4.72 +unsigned int load_vertex_shader(const char *fname)
    4.73 +{
    4.74 +	return load_shader(fname, GL_VERTEX_SHADER);
    4.75 +}
    4.76 +
    4.77 +unsigned int load_pixel_shader(const char *fname)
    4.78 +{
    4.79 +	return load_shader(fname, GL_FRAGMENT_SHADER);
    4.80 +}
    4.81 +
    4.82 +unsigned int load_shader(const char *fname, unsigned int sdr_type)
    4.83 +{
    4.84 +#if defined(unix) || defined(__unix__)
    4.85 +	struct stat st;
    4.86 +#endif
    4.87 +	unsigned int sdr;
    4.88 +	size_t filesize;
    4.89 +	FILE *fp;
    4.90 +	char *src;
    4.91 +
    4.92 +	if(!(fp = fopen(fname, "r"))) {
    4.93 +		fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno));
    4.94 +		return 0;
    4.95 +	}
    4.96 +
    4.97 +#if defined(unix) || defined(__unix__)
    4.98 +	fstat(fileno(fp), &st);
    4.99 +	filesize = st.st_size;
   4.100 +#else
   4.101 +	fseek(fp, 0, SEEK_END);
   4.102 +	filesize = ftell(fp);
   4.103 +	fseek(fp, 0, SEEK_SET);
   4.104 +#endif	/* unix */
   4.105 +
   4.106 +	if(!(src = malloc(filesize + 1))) {
   4.107 +		fclose(fp);
   4.108 +		return 0;
   4.109 +	}
   4.110 +	fread(src, 1, filesize, fp);
   4.111 +	src[filesize] = 0;
   4.112 +	fclose(fp);
   4.113 +
   4.114 +	fprintf(stderr, "compiling %s shader: %s... ", (sdr_type == GL_VERTEX_SHADER ? "vertex" : "pixel"), fname);
   4.115 +	sdr = create_shader(src, sdr_type);
   4.116 +
   4.117 +	free(src);
   4.118 +	return sdr;
   4.119 +}
   4.120 +
   4.121 +
   4.122 +unsigned int get_vertex_shader(const char *fname)
   4.123 +{
   4.124 +	return get_shader(fname, GL_VERTEX_SHADER);
   4.125 +}
   4.126 +
   4.127 +unsigned int get_pixel_shader(const char *fname)
   4.128 +{
   4.129 +	return get_shader(fname, GL_FRAGMENT_SHADER);
   4.130 +}
   4.131 +
   4.132 +unsigned int get_shader(const char *fname, unsigned int sdr_type)
   4.133 +{
   4.134 +	unsigned int sdr;
   4.135 +	if(!(sdr = load_shader(fname, sdr_type))) {
   4.136 +		return 0;
   4.137 +	}
   4.138 +	return sdr;
   4.139 +}
   4.140 +
   4.141 +
   4.142 +/* ---- gpu programs ---- */
   4.143 +
   4.144 +unsigned int create_program(void)
   4.145 +{
   4.146 +	unsigned int prog = glCreateProgram();
   4.147 +	assert(glGetError() == GL_NO_ERROR);
   4.148 +	return prog;
   4.149 +}
   4.150 +
   4.151 +unsigned int create_program_link(unsigned int vs, unsigned int ps)
   4.152 +{
   4.153 +	unsigned int prog;
   4.154 +
   4.155 +	if(!(prog = create_program())) {
   4.156 +		return 0;
   4.157 +	}
   4.158 +
   4.159 +	if(vs) {
   4.160 +		attach_shader(prog, vs);
   4.161 +		assert(glGetError() == GL_NO_ERROR);
   4.162 +	}
   4.163 +	if(ps) {
   4.164 +		attach_shader(prog, ps);
   4.165 +		assert(glGetError() == GL_NO_ERROR);
   4.166 +	}
   4.167 +
   4.168 +	if(link_program(prog) == -1) {
   4.169 +		free_program(prog);
   4.170 +		return 0;
   4.171 +	}
   4.172 +	return prog;
   4.173 +}
   4.174 +
   4.175 +unsigned int create_program_load(const char *vfile, const char *pfile)
   4.176 +{
   4.177 +	unsigned int vs = 0, ps = 0;
   4.178 +
   4.179 +	if(vfile && !(vs = get_vertex_shader(vfile))) {
   4.180 +		return 0;
   4.181 +	}
   4.182 +	if(pfile && !(ps = get_pixel_shader(pfile))) {
   4.183 +		return 0;
   4.184 +	}
   4.185 +	return create_program_link(vs, ps);
   4.186 +}
   4.187 +
   4.188 +void free_program(unsigned int sdr)
   4.189 +{
   4.190 +	glDeleteProgram(sdr);
   4.191 +}
   4.192 +
   4.193 +void attach_shader(unsigned int prog, unsigned int sdr)
   4.194 +{
   4.195 +	glAttachShader(prog, sdr);
   4.196 +	assert(glGetError() == GL_NO_ERROR);
   4.197 +}
   4.198 +
   4.199 +int link_program(unsigned int prog)
   4.200 +{
   4.201 +	int linked, info_len, retval = 0;
   4.202 +	char *info_str = 0;
   4.203 +
   4.204 +	glLinkProgram(prog);
   4.205 +	assert(glGetError() == GL_NO_ERROR);
   4.206 +	glGetProgramiv(prog, GL_LINK_STATUS, &linked);
   4.207 +	assert(glGetError() == GL_NO_ERROR);
   4.208 +	glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len);
   4.209 +	assert(glGetError() == GL_NO_ERROR);
   4.210 +
   4.211 +	if(info_len) {
   4.212 +		if((info_str = malloc(info_len + 1))) {
   4.213 +			glGetProgramInfoLog(prog, info_len, 0, info_str);
   4.214 +			assert(glGetError() == GL_NO_ERROR);
   4.215 +		}
   4.216 +	}
   4.217 +
   4.218 +	if(linked) {
   4.219 +		fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str);
   4.220 +	} else {
   4.221 +		fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str);
   4.222 +		retval = -1;
   4.223 +	}
   4.224 +
   4.225 +	free(info_str);
   4.226 +	return retval;
   4.227 +}
   4.228 +
   4.229 +int bind_program(unsigned int prog)
   4.230 +{
   4.231 +	GLenum err;
   4.232 +
   4.233 +	glUseProgram(prog);
   4.234 +	if(prog && (err = glGetError()) != GL_NO_ERROR) {
   4.235 +		/* maybe the program is not linked, try linking first */
   4.236 +		if(err == GL_INVALID_OPERATION) {
   4.237 +			if(link_program(prog) == -1) {
   4.238 +				return -1;
   4.239 +			}
   4.240 +			glUseProgram(prog);
   4.241 +			return glGetError() == GL_NO_ERROR ? 0 : -1;
   4.242 +		}
   4.243 +		return -1;
   4.244 +	}
   4.245 +	return 0;
   4.246 +}
   4.247 +
   4.248 +/* ugly but I'm not going to write the same bloody code over and over */
   4.249 +#define BEGIN_UNIFORM_CODE \
   4.250 +	int loc, curr_prog; \
   4.251 +	glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \
   4.252 +	if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \
   4.253 +		return -1; \
   4.254 +	} \
   4.255 +	if((loc = glGetUniformLocation(prog, name)) != -1)
   4.256 +
   4.257 +#define END_UNIFORM_CODE \
   4.258 +	if((unsigned int)curr_prog != prog) { \
   4.259 +		bind_program(curr_prog); \
   4.260 +	} \
   4.261 +	return loc == -1 ? -1 : 0
   4.262 +
   4.263 +int set_uniform_int(unsigned int prog, const char *name, int val)
   4.264 +{
   4.265 +	BEGIN_UNIFORM_CODE {
   4.266 +		glUniform1i(loc, val);
   4.267 +	}
   4.268 +	END_UNIFORM_CODE;
   4.269 +}
   4.270 +
   4.271 +int set_uniform_float(unsigned int prog, const char *name, float val)
   4.272 +{
   4.273 +	BEGIN_UNIFORM_CODE {
   4.274 +		glUniform1f(loc, val);
   4.275 +	}
   4.276 +	END_UNIFORM_CODE;
   4.277 +}
   4.278 +
   4.279 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z)
   4.280 +{
   4.281 +	BEGIN_UNIFORM_CODE {
   4.282 +		glUniform3f(loc, x, y, z);
   4.283 +	}
   4.284 +	END_UNIFORM_CODE;
   4.285 +}
   4.286 +
   4.287 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w)
   4.288 +{
   4.289 +	BEGIN_UNIFORM_CODE {
   4.290 +		glUniform4f(loc, x, y, z, w);
   4.291 +	}
   4.292 +	END_UNIFORM_CODE;
   4.293 +}
   4.294 +
   4.295 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat)
   4.296 +{
   4.297 +	BEGIN_UNIFORM_CODE {
   4.298 +		glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
   4.299 +	}
   4.300 +	END_UNIFORM_CODE;
   4.301 +}
   4.302 +
   4.303 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat)
   4.304 +{
   4.305 +	BEGIN_UNIFORM_CODE {
   4.306 +		glUniformMatrix4fv(loc, 1, GL_TRUE, mat);
   4.307 +	}
   4.308 +	END_UNIFORM_CODE;
   4.309 +}
   4.310 +
   4.311 +int get_attrib_loc(unsigned int prog, const char *name)
   4.312 +{
   4.313 +	int loc, curr_prog;
   4.314 +
   4.315 +	glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog);
   4.316 +	if((unsigned int)curr_prog != prog && bind_program(prog) == -1) {
   4.317 +		return -1;
   4.318 +	}
   4.319 +
   4.320 +	loc = glGetAttribLocation(prog, (char*)name);
   4.321 +
   4.322 +	if((unsigned int)curr_prog != prog) {
   4.323 +		bind_program(curr_prog);
   4.324 +	}
   4.325 +	return loc;
   4.326 +}
   4.327 +
   4.328 +void set_attrib_float3(int attr_loc, float x, float y, float z)
   4.329 +{
   4.330 +	glVertexAttrib3f(attr_loc, x, y, z);
   4.331 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/prototype/src/sdr.h	Sun Aug 19 23:09:30 2012 +0300
     5.3 @@ -0,0 +1,49 @@
     5.4 +#ifndef SDR_H_
     5.5 +#define SDR_H_
     5.6 +
     5.7 +#ifdef __cplusplus
     5.8 +extern "C" {
     5.9 +#endif	/* __cplusplus */
    5.10 +
    5.11 +/* ---- shaders ---- */
    5.12 +unsigned int create_vertex_shader(const char *src);
    5.13 +unsigned int create_pixel_shader(const char *src);
    5.14 +unsigned int create_shader(const char *src, unsigned int sdr_type);
    5.15 +void free_shader(unsigned int sdr);
    5.16 +
    5.17 +unsigned int load_vertex_shader(const char *fname);
    5.18 +unsigned int load_pixel_shader(const char *fname);
    5.19 +unsigned int load_shader(const char *src, unsigned int sdr_type);
    5.20 +
    5.21 +unsigned int get_vertex_shader(const char *fname);
    5.22 +unsigned int get_pixel_shader(const char *fname);
    5.23 +unsigned int get_shader(const char *fname, unsigned int sdr_type);
    5.24 +
    5.25 +int add_shader(const char *fname, unsigned int sdr);
    5.26 +int remove_shader(const char *fname);
    5.27 +
    5.28 +/* ---- gpu programs ---- */
    5.29 +unsigned int create_program(void);
    5.30 +unsigned int create_program_link(unsigned int vs, unsigned int ps);
    5.31 +unsigned int create_program_load(const char *vfile, const char *pfile);
    5.32 +void free_program(unsigned int sdr);
    5.33 +
    5.34 +void attach_shader(unsigned int prog, unsigned int sdr);
    5.35 +int link_program(unsigned int prog);
    5.36 +int bind_program(unsigned int prog);
    5.37 +
    5.38 +int set_uniform_int(unsigned int prog, const char *name, int val);
    5.39 +int set_uniform_float(unsigned int prog, const char *name, float val);
    5.40 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z);
    5.41 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w);
    5.42 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat);
    5.43 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat);
    5.44 +
    5.45 +int get_attrib_loc(unsigned int prog, const char *name);
    5.46 +void set_attrib_float3(int attr_loc, float x, float y, float z);
    5.47 +
    5.48 +#ifdef __cplusplus
    5.49 +}
    5.50 +#endif	/* __cplusplus */
    5.51 +
    5.52 +#endif	/* SDR_H_ */