dungeon_crawler

changeset 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 38e16366efc2
children 6d71dd4760f9
files prototype/sdr/fallback.p.glsl prototype/sdr/fallback.v.glsl prototype/src/light.cc prototype/src/main.cc prototype/src/material.cc prototype/src/renderer.cc prototype/src/renderer.h prototype/src/renderer_deferred.cc prototype/src/renderer_deferred.h prototype/src/tile.cc
diffstat 10 files changed, 526 insertions(+), 287 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/prototype/sdr/fallback.p.glsl	Thu Aug 30 05:35:00 2012 +0300
     1.3 @@ -0,0 +1,38 @@
     1.4 +uniform sampler2D tex_dif, tex_norm;
     1.5 +
     1.6 +varying vec3 pos, norm, tang;
     1.7 +
     1.8 +const float fog_start = 3.0;
     1.9 +const float fog_end = 6.0;
    1.10 +
    1.11 +void main()
    1.12 +{
    1.13 +	vec3 texel = texture2D(tex_dif, gl_TexCoord[0].st).xyz;
    1.14 +
    1.15 +	vec3 n = normalize(norm);
    1.16 +	vec3 t = normalize(tang);
    1.17 +	vec3 b = cross(n, t);
    1.18 +
    1.19 +	mat3 tbn_mat = mat3(
    1.20 +			t.x, b.x, n.x,
    1.21 +			t.y, b.y, n.y,
    1.22 +			t.z, b.z, n.z);
    1.23 +
    1.24 +
    1.25 +	const vec3 lpos = vec3(0.0, 0.0, -0.5);
    1.26 +	vec3 ldir = tbn_mat * normalize(lpos - pos);
    1.27 +
    1.28 +	const vec3 vdir = vec3(0.0, 0.0, 1.0);
    1.29 +	vec3 hvec = normalize(vdir + ldir);
    1.30 +
    1.31 +	n = normalize(texture2D(tex_norm, gl_TexCoord[0].st).xyz * 2.0 - 1.0);
    1.32 +	float ndotl = max(dot(n, ldir), 0.0);
    1.33 +	float ndoth = max(dot(n, hvec), 0.0);
    1.34 +
    1.35 +	vec3 diffuse = gl_FrontMaterial.diffuse.xyz * texel * ndotl;
    1.36 +	vec3 specular = gl_FrontMaterial.specular.xyz * pow(ndoth, gl_FrontMaterial.shininess);
    1.37 +
    1.38 +	float fog = clamp((fog_end + pos.z) / (fog_end - fog_start), 0.0, 1.0);
    1.39 +
    1.40 +	gl_FragColor = vec4((diffuse + specular) * fog, 1.0);
    1.41 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/prototype/sdr/fallback.v.glsl	Thu Aug 30 05:35:00 2012 +0300
     2.3 @@ -0,0 +1,13 @@
     2.4 +attribute vec3 attr_tangent;
     2.5 +
     2.6 +varying vec3 pos, norm, tang;
     2.7 +
     2.8 +void main()
     2.9 +{
    2.10 +	gl_Position = ftransform();
    2.11 +	pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
    2.12 +	norm = gl_NormalMatrix * gl_Normal;
    2.13 +	tang = gl_NormalMatrix * attr_tangent;
    2.14 +
    2.15 +	gl_TexCoord[0] = gl_MultiTexCoord0;
    2.16 +}
     3.1 --- a/prototype/src/light.cc	Thu Aug 30 03:05:04 2012 +0300
     3.2 +++ b/prototype/src/light.cc	Thu Aug 30 05:35:00 2012 +0300
     3.3 @@ -114,7 +114,7 @@
     3.4  
     3.5  void PointLight::draw() const
     3.6  {
     3.7 -	unsigned int sdr = get_deferred_shader();
     3.8 +	unsigned int sdr = rend->get_current_program();
     3.9  	if(sdr) {
    3.10  		int loc;
    3.11  		if((loc = glGetUniformLocation(sdr, "light_radius")) != -1) {
     4.1 --- a/prototype/src/main.cc	Thu Aug 30 03:05:04 2012 +0300
     4.2 +++ b/prototype/src/main.cc	Thu Aug 30 05:35:00 2012 +0300
     4.3 @@ -8,6 +8,7 @@
     4.4  #include "datapath.h"
     4.5  #include "tileset.h"
     4.6  #include "renderer.h"
     4.7 +#include "renderer_deferred.h"
     4.8  #include "cmdcon.h"
     4.9  #include "cfg.h"
    4.10  #include "timer.h"
    4.11 @@ -70,11 +71,15 @@
    4.12  
    4.13  bool init(int xsz, int ysz)
    4.14  {
    4.15 +	// backup light for the forward crappy renderer
    4.16  	glEnable(GL_LIGHTING);
    4.17  	glEnable(GL_LIGHT0);
    4.18 -	float ldir[] = {-1, 1, 2, 0};
    4.19 +
    4.20 +	float ldir[] = {0, 0, -0.5, 1};
    4.21  	glLightfv(GL_LIGHT0, GL_POSITION, ldir);
    4.22 -	glEnable(GL_NORMALIZE);
    4.23 +	float lcol[] = {1, 1, 1, 1};
    4.24 +	glLightfv(GL_LIGHT0, GL_DIFFUSE, lcol);
    4.25 +	glLightfv(GL_LIGHT0, GL_SPECULAR, lcol);
    4.26  
    4.27  	glEnable(GL_DEPTH_TEST);
    4.28  	glEnable(GL_CULL_FACE);
    4.29 @@ -84,8 +89,15 @@
    4.30  	add_data_path("data");
    4.31  	add_data_path("sdr");
    4.32  
    4.33 -	if(!init_renderer(xsz, ysz)) {
    4.34 -		return false;
    4.35 +	rend = new DeferredRenderer();
    4.36 +	if(!rend->init(xsz, ysz)) {
    4.37 +		printf("falling back to crappy renderer...\n");
    4.38 +
    4.39 +		rend = new FwdRenderer();
    4.40 +		if(!rend->init(xsz, ysz)) {
    4.41 +			fprintf(stderr, "failed to create renderer\n");
    4.42 +			return false;
    4.43 +		}
    4.44  	}
    4.45  
    4.46  	if(!init_cmdcon()) {
    4.47 @@ -115,8 +127,7 @@
    4.48  {
    4.49  	delete level;
    4.50  	delete tileset;
    4.51 -
    4.52 -	destroy_renderer();
    4.53 +	delete rend;
    4.54  
    4.55  	cleanup_cmdcon();
    4.56  }
    4.57 @@ -165,15 +176,13 @@
    4.58  
    4.59  	glutSwapBuffers();
    4.60  	assert(glGetError() == GL_NO_ERROR);
    4.61 -
    4.62 -	usleep(10000);
    4.63  }
    4.64  
    4.65  void draw()
    4.66  {
    4.67 -	glClear(GL_COLOR_BUFFER_BIT);
    4.68 +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    4.69  
    4.70 -	render_deferred(level);
    4.71 +	rend->render(level);
    4.72  
    4.73  	if(show_con) {
    4.74  		draw_cmdcon();
    4.75 @@ -240,7 +249,7 @@
    4.76  	cfg.width = x;
    4.77  	cfg.height = y;
    4.78  
    4.79 -	resize_renderer(x, y);
    4.80 +	rend->resize(x, y);
    4.81  }
    4.82  
    4.83  static bool stereo_shift_pressed;
     5.1 --- a/prototype/src/material.cc	Thu Aug 30 03:05:04 2012 +0300
     5.2 +++ b/prototype/src/material.cc	Thu Aug 30 05:35:00 2012 +0300
     5.3 @@ -3,6 +3,7 @@
     5.4  #include <assimp/material.h>
     5.5  #include "opengl.h"
     5.6  #include "material.h"
     5.7 +#include "renderer.h"
     5.8  
     5.9  extern bool ass_obj_hack;
    5.10  
    5.11 @@ -74,7 +75,7 @@
    5.12  		glDisable(GL_TEXTURE_2D);
    5.13  	}
    5.14  
    5.15 -	if(tex[TEXTYPE_NORMAL]) {
    5.16 +	if(rend->get_current_program() && tex[TEXTYPE_NORMAL]) {
    5.17  		glActiveTextureARB(GL_TEXTURE1);
    5.18  		glBindTexture(GL_TEXTURE_2D, tex[TEXTYPE_NORMAL]);
    5.19  		glEnable(GL_TEXTURE_2D);
     6.1 --- a/prototype/src/renderer.cc	Thu Aug 30 03:05:04 2012 +0300
     6.2 +++ b/prototype/src/renderer.cc	Thu Aug 30 05:35:00 2012 +0300
     6.3 @@ -1,247 +1,97 @@
     6.4 -#include <stdio.h>
     6.5 -#include <stdlib.h>
     6.6 -#include <string.h>
     6.7 -#include <limits.h>
     6.8 -#include <assert.h>
     6.9  #include "opengl.h"
    6.10  #include "renderer.h"
    6.11  #include "level.h"
    6.12  #include "sdr.h"
    6.13  #include "datapath.h"
    6.14  
    6.15 -#undef DBG_VIS_MRT
    6.16 +static unsigned int load_sdr(const char *vfname, const char *pfname);
    6.17  
    6.18 -#ifdef DBG_VIS_MRT
    6.19 -static void draw_deferred_debug();
    6.20 -#endif
    6.21 +Renderer *rend;
    6.22  
    6.23 -static bool create_fbo(int xsz, int ysz);
    6.24 -static unsigned int load_sdr(const char *vfname, const char *pfname);
    6.25 -static int round_pow2(int x);
    6.26  
    6.27 +Renderer::Renderer()
    6.28 +{
    6.29 +	width = height = 0;
    6.30 +}
    6.31  
    6.32 -#define MRT_COUNT	3
    6.33 -static unsigned int mrt_tex[MRT_COUNT];
    6.34 +Renderer::~Renderer()
    6.35 +{
    6.36 +}
    6.37  
    6.38 -static unsigned int mrt_prog;
    6.39 -static unsigned int deferred_omni, deferred_debug;
    6.40 +bool Renderer::init(int xsz, int ysz)
    6.41 +{
    6.42 +	width = xsz;
    6.43 +	height = ysz;
    6.44  
    6.45 -static unsigned int fbo, rbuf_depth;
    6.46 -static const char *fbstname[] = {
    6.47 -	"GL_FRAMEBUFFER_COMPLETE",
    6.48 -	"GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
    6.49 -	"GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
    6.50 -	"no such fbo error",
    6.51 -	"GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
    6.52 -	"GL_FRAMEBUFFER_INCOMPLETE_FORMATS",
    6.53 -	"GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER",
    6.54 -	"GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER",
    6.55 -	"GL_FRAMEBUFFER_UNSUPPORTED"
    6.56 -};
    6.57 +	rend = this;
    6.58 +	return true;
    6.59 +}
    6.60  
    6.61 -static int fb_xsz, fb_ysz, tex_xsz, tex_ysz;
    6.62 +int Renderer::get_tangent_location() const
    6.63 +{
    6.64 +	return -1;
    6.65 +}
    6.66  
    6.67 +unsigned int Renderer::get_current_program() const
    6.68 +{
    6.69 +	return 0;
    6.70 +}
    6.71  
    6.72 +void Renderer::resize(int xsz, int ysz)
    6.73 +{
    6.74 +	width = xsz;
    6.75 +	height = ysz;
    6.76 +}
    6.77  
    6.78 -bool init_renderer(int xsz, int ysz)
    6.79 +
    6.80 +// ---- fallback forward renderer ----
    6.81 +FwdRenderer::FwdRenderer()
    6.82  {
    6.83 -	if(!GLEW_ARB_texture_float) {
    6.84 -		fprintf(stderr, "Error: OpenGL implementation doesn't support floating point textures\n");
    6.85 -		return false;
    6.86 +	sdrprog = 0;
    6.87 +	tang_attr = -1;
    6.88 +}
    6.89 +
    6.90 +FwdRenderer::~FwdRenderer()
    6.91 +{
    6.92 +	if(sdrprog) {
    6.93 +		free_program(sdrprog);
    6.94  	}
    6.95 -	if(!GLEW_ARB_draw_buffers) {
    6.96 -		fprintf(stderr, "Error: OpenGL implementation doesn't support multiple render targets\n");
    6.97 -		return false;
    6.98 -	}
    6.99 +}
   6.100  
   6.101 -	int max_draw_buf;
   6.102 -	glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buf);
   6.103 -	printf("max draw buffers: %d\n", max_draw_buf);
   6.104 -	if(max_draw_buf < MRT_COUNT) {
   6.105 -		fprintf(stderr, "OpenGL implementation doesn't support enough draw buffers\n");
   6.106 -		return false;
   6.107 -	}
   6.108 +bool FwdRenderer::init(int xsz, int ysz)
   6.109 +{
   6.110 +	width = xsz;
   6.111 +	height = ysz;
   6.112  
   6.113 -	if(!create_fbo(xsz, ysz)) {
   6.114 -		return false;
   6.115 -	}
   6.116 -	CHECKGLERR;
   6.117 -
   6.118 -	if(!(mrt_prog = load_sdr("mrt.v.glsl", "mrt.p.glsl"))) {
   6.119 -		return false;
   6.120 -	}
   6.121 -	set_uniform_int(mrt_prog, "tex_dif", 0);
   6.122 -	set_uniform_int(mrt_prog, "tex_norm", 1);
   6.123 -
   6.124 -	if(!(deferred_debug = load_sdr("deferred.v.glsl", "deferred.p.glsl"))) {
   6.125 -		return false;
   6.126 -	}
   6.127 -	for(int i=0; i<MRT_COUNT; i++) {
   6.128 -		char uname[32];
   6.129 -		sprintf(uname, "mrt%d", i);
   6.130 -		set_uniform_int(deferred_debug, uname, i);
   6.131 -	}
   6.132 -
   6.133 -	if(!(deferred_omni = load_sdr("deferred_omni.v.glsl", "deferred_omni.p.glsl"))) {
   6.134 -		return false;
   6.135 -	}
   6.136 -	for(int i=0; i<MRT_COUNT; i++) {
   6.137 -		char uname[32];
   6.138 -		sprintf(uname, "mrt%d", i);
   6.139 -		set_uniform_int(deferred_omni, uname, i);
   6.140 +	if(glUseProgram && (sdrprog = load_sdr("fallback.v.glsl", "fallback.p.glsl"))) {
   6.141 +		tang_attr = get_attrib_loc(sdrprog, "attr_tangent");
   6.142 +		set_uniform_int(sdrprog, "tex_dif", 0);
   6.143 +		set_uniform_int(sdrprog, "tex_norm", 1);
   6.144  	}
   6.145  	return true;
   6.146  }
   6.147  
   6.148 -void destroy_renderer()
   6.149 +int FwdRenderer::get_tangent_location() const
   6.150  {
   6.151 -	free_program(mrt_prog);
   6.152 -	free_program(deferred_omni);
   6.153 -
   6.154 -	glDeleteTextures(MRT_COUNT, mrt_tex);
   6.155 -	glDeleteFramebuffersEXT(1, &fbo);
   6.156 +	return tang_attr;
   6.157  }
   6.158  
   6.159 -unsigned int get_deferred_shader(void)
   6.160 +unsigned int FwdRenderer::get_current_program() const
   6.161  {
   6.162 -	return deferred_omni;
   6.163 +	return sdrprog;
   6.164  }
   6.165  
   6.166 -int get_tangent_location(void)
   6.167 +void FwdRenderer::render(const Level *level) const
   6.168  {
   6.169 -	return get_attrib_loc(mrt_prog, "attr_tangent");
   6.170 -}
   6.171 +	glPushAttrib(GL_ENABLE_BIT);
   6.172 +	glUseProgram(sdrprog);
   6.173  
   6.174 -void resize_renderer(int xsz, int ysz)
   6.175 -{
   6.176 -	fb_xsz = xsz;
   6.177 -	fb_ysz = ysz;
   6.178 -
   6.179 -	// if we need a bigger rendertarget resize all colorbuffer textures and the depth buffer
   6.180 -	if(xsz > tex_xsz || ysz > tex_ysz) {
   6.181 -		tex_xsz = round_pow2(xsz);
   6.182 -		tex_ysz = round_pow2(ysz);
   6.183 -
   6.184 -		for(int i=0; i<MRT_COUNT; i++) {
   6.185 -			glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
   6.186 -			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, tex_xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, 0);
   6.187 -		}
   6.188 -
   6.189 -		glBindRenderbufferEXT(GL_RENDERBUFFER, rbuf_depth);
   6.190 -		glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
   6.191 -	}
   6.192 -
   6.193 -
   6.194 -	// update the texture coordinate scaling factors
   6.195 -	float tex_scale_x = (float)fb_xsz / tex_xsz;
   6.196 -	float tex_scale_y = (float)fb_ysz / tex_ysz;
   6.197 -
   6.198 -	set_uniform_float2(deferred_omni, "tex_scale", tex_scale_x, tex_scale_y);
   6.199 -	set_uniform_float2(deferred_omni, "fb_size", fb_xsz, fb_ysz);
   6.200 -
   6.201 -	set_uniform_float2(deferred_debug, "tex_scale", tex_scale_x, tex_scale_y);
   6.202 -}
   6.203 -
   6.204 -void render_deferred(const Level *level)
   6.205 -{
   6.206 -	// render into the MRT buffers
   6.207 -	glUseProgram(mrt_prog);
   6.208 -	glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
   6.209 -
   6.210 -	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   6.211 +	glEnable(GL_LIGHTING);
   6.212  	level->draw();
   6.213  
   6.214 -	glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
   6.215 -
   6.216 -#ifdef DBG_VIS_MRT
   6.217 -	draw_deferred_debug();
   6.218 -#else
   6.219 -
   6.220 -	// post-process lighting
   6.221 -	glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
   6.222 -
   6.223 -	glEnable(GL_BLEND);
   6.224 -	glBlendFunc(GL_ONE, GL_ONE);
   6.225 -
   6.226 -	glDisable(GL_LIGHTING);
   6.227 -	glDisable(GL_DEPTH_TEST);
   6.228 -	glCullFace(GL_FRONT);
   6.229 -
   6.230 -	glUseProgram(deferred_omni);
   6.231 -	for(int i=0; i<MRT_COUNT; i++) {
   6.232 -		glActiveTexture(GL_TEXTURE0 + i);
   6.233 -		glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
   6.234 -		glEnable(GL_TEXTURE_2D);
   6.235 -	}
   6.236 -
   6.237 -	glDepthMask(0);
   6.238 -	level->draw_lights();
   6.239 -	glDepthMask(1);
   6.240 -
   6.241 -	for(int i=0; i<MRT_COUNT; i++) {
   6.242 -		glActiveTexture(GL_TEXTURE0 + MRT_COUNT - i - 1);
   6.243 -		glDisable(GL_TEXTURE_2D);
   6.244 -	}
   6.245 +	glPopAttrib();
   6.246  
   6.247  	glUseProgram(0);
   6.248 -	glPopAttrib();
   6.249 -#endif	// DBG_VIS_MRT
   6.250 -}
   6.251 -
   6.252 -static bool create_fbo(int xsz, int ysz)
   6.253 -{
   6.254 -	unsigned int clamp = GLEW_ARB_texture_border_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP;
   6.255 -
   6.256 -	// round the texture size up to the next power of 2
   6.257 -	tex_xsz = round_pow2(xsz);
   6.258 -	tex_ysz = round_pow2(ysz);
   6.259 -	fb_xsz = xsz;
   6.260 -	fb_ysz = ysz;
   6.261 -
   6.262 -	if(!glGenFramebuffersEXT) {
   6.263 -		fprintf(stderr, "FBO support missing\n");
   6.264 -		return false;
   6.265 -	}
   6.266 -	glGenFramebuffersEXT(1, &fbo);
   6.267 -	glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
   6.268 -
   6.269 -	glGenTextures(MRT_COUNT, mrt_tex);
   6.270 -	for(int i=0; i<MRT_COUNT; i++) {
   6.271 -		glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
   6.272 -		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
   6.273 -		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
   6.274 -		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   6.275 -		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   6.276 -		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, tex_xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, 0);
   6.277 -
   6.278 -		// attach to fbo
   6.279 -		glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
   6.280 -				GL_TEXTURE_2D, mrt_tex[i], 0);
   6.281 -		CHECKGLERR;
   6.282 -	}
   6.283 -
   6.284 -	static GLenum draw_bufs[] = {
   6.285 -		GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT,
   6.286 -		GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT,
   6.287 -		GL_COLOR_ATTACHMENT4_EXT, GL_COLOR_ATTACHMENT5_EXT,
   6.288 -		GL_COLOR_ATTACHMENT6_EXT, GL_COLOR_ATTACHMENT7_EXT
   6.289 -	};
   6.290 -	glDrawBuffersARB(MRT_COUNT, draw_bufs);
   6.291 -
   6.292 -	glGenRenderbuffersEXT(1, &rbuf_depth);
   6.293 -	glBindRenderbufferEXT(GL_RENDERBUFFER, rbuf_depth);
   6.294 -	glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
   6.295 -	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_depth);
   6.296 -
   6.297 -	int fbst = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
   6.298 -	if(fbst != GL_FRAMEBUFFER_COMPLETE) {
   6.299 -		fprintf(stderr, "incomplete fbo: %u (%s)\n", fbo, fbstname[fbst - GL_FRAMEBUFFER_COMPLETE]);
   6.300 -		return false;
   6.301 -	}
   6.302 -	CHECKGLERR;
   6.303 -
   6.304 -	glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
   6.305 -	return true;
   6.306  }
   6.307  
   6.308  static unsigned int load_sdr(const char *vfname, const char *pfname)
   6.309 @@ -266,61 +116,3 @@
   6.310  	}
   6.311  	return prog;
   6.312  }
   6.313 -
   6.314 -static int round_pow2(int x)
   6.315 -{
   6.316 -	x--;
   6.317 -	x = (x >> 1) | x;
   6.318 -	x = (x >> 2) | x;
   6.319 -	x = (x >> 4) | x;
   6.320 -	x = (x >> 8) | x;
   6.321 -	x = (x >> 16) | x;
   6.322 -	return x + 1;
   6.323 -}
   6.324 -
   6.325 -#ifdef DBG_VIS_MRT
   6.326 -// visualize the MRT buffers
   6.327 -static void draw_deferred_debug()
   6.328 -{
   6.329 -	glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
   6.330 -	glUseProgram(deferred_debug);
   6.331 -	glDisable(GL_DEPTH_TEST);
   6.332 -
   6.333 -	glMatrixMode(GL_PROJECTION);
   6.334 -	glPushMatrix();
   6.335 -	glLoadIdentity();
   6.336 -	glMatrixMode(GL_MODELVIEW);
   6.337 -	glPushMatrix();
   6.338 -	glLoadIdentity();
   6.339 -
   6.340 -	for(int i=0; i<MRT_COUNT; i++) {
   6.341 -		glActiveTexture(GL_TEXTURE0 + i);
   6.342 -		glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
   6.343 -		glEnable(GL_TEXTURE_2D);
   6.344 -	}
   6.345 -
   6.346 -	glBegin(GL_QUADS);
   6.347 -	glTexCoord2f(0, 0);
   6.348 -	glVertex2f(-1, -1);
   6.349 -	glTexCoord2f(1, 0);
   6.350 -	glVertex2f(1, -1);
   6.351 -	glTexCoord2f(1, 1);
   6.352 -	glVertex2f(1, 1);
   6.353 -	glTexCoord2f(0, 1);
   6.354 -	glVertex2f(-1, 1);
   6.355 -	glEnd();
   6.356 -
   6.357 -	for(int i=0; i<MRT_COUNT; i++) {
   6.358 -		glActiveTexture(GL_TEXTURE0 + MRT_COUNT - i - 1);
   6.359 -		glDisable(GL_TEXTURE_2D);
   6.360 -	}
   6.361 -
   6.362 -	glMatrixMode(GL_PROJECTION);
   6.363 -	glPopMatrix();
   6.364 -	glMatrixMode(GL_MODELVIEW);
   6.365 -	glPopMatrix();
   6.366 -
   6.367 -	glUseProgram(0);
   6.368 -	glPopAttrib();
   6.369 -}
   6.370 -#endif
     7.1 --- a/prototype/src/renderer.h	Thu Aug 30 03:05:04 2012 +0300
     7.2 +++ b/prototype/src/renderer.h	Thu Aug 30 05:35:00 2012 +0300
     7.3 @@ -3,15 +3,44 @@
     7.4  
     7.5  class Level;
     7.6  
     7.7 -bool init_renderer(int xsz, int ysz);
     7.8 -void destroy_renderer();
     7.9 +class Renderer {
    7.10 +protected:
    7.11 +	int width, height;
    7.12  
    7.13 -unsigned int get_deferred_shader(void);
    7.14 -int get_tangent_location(void);
    7.15 +public:
    7.16 +	Renderer();
    7.17 +	virtual ~Renderer();
    7.18  
    7.19 -void resize_renderer(int xsz, int ysz);
    7.20 +	virtual bool init(int xsz, int ysz);
    7.21  
    7.22 -void update_renderer(unsigned long msec, float dt);
    7.23 -void render_deferred(const Level *level);
    7.24 +	virtual int get_tangent_location() const;
    7.25 +	virtual unsigned int get_current_program() const;
    7.26 +
    7.27 +	virtual void resize(int xsz, int ysz);
    7.28 +
    7.29 +	virtual void render(const Level *level) const = 0;
    7.30 +};
    7.31 +
    7.32 +
    7.33 +class FwdRenderer : public Renderer {
    7.34 +protected:
    7.35 +	unsigned int sdrprog;
    7.36 +	int tang_attr;
    7.37 +
    7.38 +public:
    7.39 +	FwdRenderer();
    7.40 +	~FwdRenderer();
    7.41 +
    7.42 +	bool init(int xsz, int ysz);
    7.43 +
    7.44 +	int get_tangent_location() const;
    7.45 +	unsigned int get_current_program() const;
    7.46 +
    7.47 +	void render(const Level *level) const;
    7.48 +};
    7.49 +
    7.50 +
    7.51 +extern Renderer *rend;
    7.52 +
    7.53  
    7.54  #endif	// RENDERER_H_
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/prototype/src/renderer_deferred.cc	Thu Aug 30 05:35:00 2012 +0300
     8.3 @@ -0,0 +1,322 @@
     8.4 +#include <stdio.h>
     8.5 +#include <stdlib.h>
     8.6 +#include <string.h>
     8.7 +#include <limits.h>
     8.8 +#include "opengl.h"
     8.9 +#include "renderer_deferred.h"
    8.10 +#include "level.h"
    8.11 +#include "sdr.h"
    8.12 +#include "datapath.h"
    8.13 +
    8.14 +static unsigned int load_sdr(const char *vfname, const char *pfname);
    8.15 +static int round_pow2(int x);
    8.16 +
    8.17 +DeferredRenderer::DeferredRenderer()
    8.18 +{
    8.19 +	fbo = rbuf_depth = 0;
    8.20 +	for(int i=0; i<MRT_COUNT; i++) {
    8.21 +		mrt_tex[i] = 0;
    8.22 +	}
    8.23 +	tex_xsz = tex_ysz = 0;
    8.24 +
    8.25 +	mrt_prog = deferred_debug = deferred_omni = 0;
    8.26 +
    8.27 +	curr_prog = 0;
    8.28 +}
    8.29 +
    8.30 +DeferredRenderer::~DeferredRenderer()
    8.31 +{
    8.32 +	if(mrt_prog) {
    8.33 +		free_program(mrt_prog);
    8.34 +	}
    8.35 +	if(deferred_omni) {
    8.36 +		free_program(deferred_omni);
    8.37 +	}
    8.38 +	if(deferred_debug) {
    8.39 +		free_program(deferred_debug);
    8.40 +	}
    8.41 +
    8.42 +	if(mrt_tex[0]) {
    8.43 +		glDeleteTextures(MRT_COUNT, mrt_tex);
    8.44 +	}
    8.45 +	if(fbo) {
    8.46 +		glDeleteFramebuffersEXT(1, &fbo);
    8.47 +	}
    8.48 +}
    8.49 +
    8.50 +bool DeferredRenderer::init(int xsz, int ysz)
    8.51 +{
    8.52 +	width = xsz;
    8.53 +	height = ysz;
    8.54 +
    8.55 +	if(!GLEW_ARB_texture_float) {
    8.56 +		fprintf(stderr, "%s: error: no floating point texture support\n", __func__);
    8.57 +		return false;
    8.58 +	}
    8.59 +	if(!GLEW_ARB_draw_buffers) {
    8.60 +		fprintf(stderr, "%s: error: no multiple render target support\n", __func__);
    8.61 +		return false;
    8.62 +	}
    8.63 +
    8.64 +	int max_draw_buf;
    8.65 +	glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buf);
    8.66 +	printf("max draw buffers: %d\n", max_draw_buf);
    8.67 +	if(max_draw_buf < MRT_COUNT) {
    8.68 +		fprintf(stderr, "%s: error: not enough draw buffers (%d), %d required\n", __func__, max_draw_buf, MRT_COUNT);
    8.69 +		return false;
    8.70 +	}
    8.71 +
    8.72 +	if(!create_fbo()) {
    8.73 +		return false;
    8.74 +	}
    8.75 +
    8.76 +	if(!(mrt_prog = load_sdr("mrt.v.glsl", "mrt.p.glsl"))) {
    8.77 +		return false;
    8.78 +	}
    8.79 +	set_uniform_int(mrt_prog, "tex_dif", 0);
    8.80 +	set_uniform_int(mrt_prog, "tex_norm", 1);
    8.81 +
    8.82 +	if(!(deferred_omni = load_sdr("deferred_omni.v.glsl", "deferred_omni.p.glsl"))) {
    8.83 +		return false;
    8.84 +	}
    8.85 +	for(int i=0; i<MRT_COUNT; i++) {
    8.86 +		char uname[32];
    8.87 +		sprintf(uname, "mrt%d", i);
    8.88 +		set_uniform_int(deferred_omni, uname, i);
    8.89 +	}
    8.90 +
    8.91 +	rend = this;
    8.92 +	return true;
    8.93 +}
    8.94 +
    8.95 +int DeferredRenderer::get_tangent_location() const
    8.96 +{
    8.97 +	return get_attrib_loc(mrt_prog, "attr_tangent");
    8.98 +}
    8.99 +
   8.100 +unsigned int DeferredRenderer::get_current_program() const
   8.101 +{
   8.102 +	return curr_prog;
   8.103 +}
   8.104 +
   8.105 +void DeferredRenderer::resize(int xsz, int ysz)
   8.106 +{
   8.107 +	width = xsz;
   8.108 +	height = ysz;
   8.109 +
   8.110 +	// if we need a bigger rendertarget ...
   8.111 +	if(xsz > tex_xsz || ysz > tex_ysz) {
   8.112 +		tex_xsz = round_pow2(xsz);
   8.113 +		tex_ysz = round_pow2(ysz);
   8.114 +
   8.115 +		// ... resize all the color buffers
   8.116 +		for(int i=0; i<MRT_COUNT; i++) {
   8.117 +			glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
   8.118 +			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, tex_xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, 0);
   8.119 +		}
   8.120 +
   8.121 +		// ... resize the depth buffer
   8.122 +		glBindRenderbufferEXT(GL_RENDERBUFFER, rbuf_depth);
   8.123 +		glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
   8.124 +	}
   8.125 +
   8.126 +	// update the texture coordinate scaling factors
   8.127 +	float tex_scale_x = (float)width / tex_xsz;
   8.128 +	float tex_scale_y = (float)height / tex_ysz;
   8.129 +
   8.130 +	set_uniform_float2(deferred_omni, "tex_scale", tex_scale_x, tex_scale_y);
   8.131 +	set_uniform_float2(deferred_omni, "fb_size", width, height);
   8.132 +}
   8.133 +
   8.134 +void DeferredRenderer::render(const Level *level) const
   8.135 +{
   8.136 +	// render into the MRT buffers
   8.137 +	glUseProgram(mrt_prog);
   8.138 +	curr_prog = mrt_prog;
   8.139 +
   8.140 +	glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
   8.141 +
   8.142 +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   8.143 +	level->draw();
   8.144 +
   8.145 +	glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
   8.146 +
   8.147 +	// post-process lighting
   8.148 +	glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
   8.149 +
   8.150 +	glEnable(GL_BLEND);
   8.151 +	glBlendFunc(GL_ONE, GL_ONE);
   8.152 +
   8.153 +	glDisable(GL_LIGHTING);
   8.154 +	glDisable(GL_DEPTH_TEST);
   8.155 +	glCullFace(GL_FRONT);
   8.156 +
   8.157 +	glUseProgram(deferred_omni);
   8.158 +	curr_prog = deferred_omni;
   8.159 +
   8.160 +	for(int i=0; i<MRT_COUNT; i++) {
   8.161 +		glActiveTexture(GL_TEXTURE0 + i);
   8.162 +		glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
   8.163 +		glEnable(GL_TEXTURE_2D);
   8.164 +	}
   8.165 +
   8.166 +	glDepthMask(0);
   8.167 +	level->draw_lights();
   8.168 +	glDepthMask(1);
   8.169 +
   8.170 +	for(int i=0; i<MRT_COUNT; i++) {
   8.171 +		glActiveTexture(GL_TEXTURE0 + MRT_COUNT - i - 1);
   8.172 +		glDisable(GL_TEXTURE_2D);
   8.173 +	}
   8.174 +
   8.175 +	glUseProgram(0);
   8.176 +	curr_prog = 0;
   8.177 +	glPopAttrib();
   8.178 +}
   8.179 +
   8.180 +static const char *fbstname[] = {
   8.181 +	"GL_FRAMEBUFFER_COMPLETE",
   8.182 +	"GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
   8.183 +	"GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
   8.184 +	"no such fbo error",
   8.185 +	"GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
   8.186 +	"GL_FRAMEBUFFER_INCOMPLETE_FORMATS",
   8.187 +	"GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER",
   8.188 +	"GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER",
   8.189 +	"GL_FRAMEBUFFER_UNSUPPORTED"
   8.190 +};
   8.191 +
   8.192 +bool DeferredRenderer::create_fbo()
   8.193 +{
   8.194 +	unsigned int clamp = GLEW_ARB_texture_border_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP;
   8.195 +
   8.196 +	// round the texture size up to the next power of 2
   8.197 +	tex_xsz = round_pow2(width);
   8.198 +	tex_ysz = round_pow2(height);
   8.199 +
   8.200 +	if(!glGenFramebuffersEXT) {
   8.201 +		fprintf(stderr, "FBO support missing\n");
   8.202 +		return false;
   8.203 +	}
   8.204 +	glGenFramebuffersEXT(1, &fbo);
   8.205 +	glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
   8.206 +
   8.207 +	glGenTextures(MRT_COUNT, mrt_tex);
   8.208 +	for(int i=0; i<MRT_COUNT; i++) {
   8.209 +		glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
   8.210 +		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
   8.211 +		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
   8.212 +		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   8.213 +		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   8.214 +		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, tex_xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, 0);
   8.215 +
   8.216 +		// attach to fbo
   8.217 +		glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
   8.218 +				GL_TEXTURE_2D, mrt_tex[i], 0);
   8.219 +		CHECKGLERR;
   8.220 +	}
   8.221 +
   8.222 +	static GLenum draw_bufs[] = {
   8.223 +		GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT,
   8.224 +		GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT,
   8.225 +		GL_COLOR_ATTACHMENT4_EXT, GL_COLOR_ATTACHMENT5_EXT,
   8.226 +		GL_COLOR_ATTACHMENT6_EXT, GL_COLOR_ATTACHMENT7_EXT
   8.227 +	};
   8.228 +	glDrawBuffersARB(MRT_COUNT, draw_bufs);
   8.229 +
   8.230 +	glGenRenderbuffersEXT(1, &rbuf_depth);
   8.231 +	glBindRenderbufferEXT(GL_RENDERBUFFER, rbuf_depth);
   8.232 +	glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
   8.233 +	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_depth);
   8.234 +
   8.235 +	int fbst = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
   8.236 +	if(fbst != GL_FRAMEBUFFER_COMPLETE) {
   8.237 +		fprintf(stderr, "incomplete fbo: %u (%s)\n", fbo, fbstname[fbst - GL_FRAMEBUFFER_COMPLETE]);
   8.238 +		return false;
   8.239 +	}
   8.240 +	CHECKGLERR;
   8.241 +
   8.242 +	glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
   8.243 +	return true;
   8.244 +}
   8.245 +
   8.246 +static unsigned int load_sdr(const char *vfname, const char *pfname)
   8.247 +{
   8.248 +	char vsfile[PATH_MAX], psfile[PATH_MAX];
   8.249 +	const char *fname;
   8.250 +	unsigned int prog;
   8.251 +
   8.252 +	if((fname = datafile_path(vfname))) {
   8.253 +		strcpy(vsfile, fname);
   8.254 +	} else {
   8.255 +		vsfile[0] = 0;
   8.256 +	}
   8.257 +	if((fname = datafile_path(pfname))) {
   8.258 +		strcpy(psfile, fname);
   8.259 +	} else {
   8.260 +		psfile[0] = 0;
   8.261 +	}
   8.262 +	if(!(prog = create_program_load(vsfile, psfile))) {
   8.263 +		fprintf(stderr, "failed to load shader program (%s, %s)\n", vsfile, psfile);
   8.264 +		return 0;
   8.265 +	}
   8.266 +	return prog;
   8.267 +}
   8.268 +
   8.269 +static int round_pow2(int x)
   8.270 +{
   8.271 +	x--;
   8.272 +	x = (x >> 1) | x;
   8.273 +	x = (x >> 2) | x;
   8.274 +	x = (x >> 4) | x;
   8.275 +	x = (x >> 8) | x;
   8.276 +	x = (x >> 16) | x;
   8.277 +	return x + 1;
   8.278 +}
   8.279 +
   8.280 +#ifdef DBG_VIS_MRT
   8.281 +// visualize the MRT buffers
   8.282 +static void draw_deferred_debug()
   8.283 +{
   8.284 +	glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
   8.285 +	glUseProgram(deferred_debug);
   8.286 +	glDisable(GL_DEPTH_TEST);
   8.287 +
   8.288 +	glMatrixMode(GL_PROJECTION);
   8.289 +	glPushMatrix();
   8.290 +	glLoadIdentity();
   8.291 +	glMatrixMode(GL_MODELVIEW);
   8.292 +	glPushMatrix();
   8.293 +	glLoadIdentity();
   8.294 +
   8.295 +	for(int i=0; i<MRT_COUNT; i++) {
   8.296 +		glActiveTexture(GL_TEXTURE0 + i);
   8.297 +		glBindTexture(GL_TEXTURE_2D, mrt_tex[i]);
   8.298 +		glEnable(GL_TEXTURE_2D);
   8.299 +	}
   8.300 +
   8.301 +	glBegin(GL_QUADS);
   8.302 +	glTexCoord2f(0, 0);
   8.303 +	glVertex2f(-1, -1);
   8.304 +	glTexCoord2f(1, 0);
   8.305 +	glVertex2f(1, -1);
   8.306 +	glTexCoord2f(1, 1);
   8.307 +	glVertex2f(1, 1);
   8.308 +	glTexCoord2f(0, 1);
   8.309 +	glVertex2f(-1, 1);
   8.310 +	glEnd();
   8.311 +
   8.312 +	for(int i=0; i<MRT_COUNT; i++) {
   8.313 +		glActiveTexture(GL_TEXTURE0 + MRT_COUNT - i - 1);
   8.314 +		glDisable(GL_TEXTURE_2D);
   8.315 +	}
   8.316 +
   8.317 +	glMatrixMode(GL_PROJECTION);
   8.318 +	glPopMatrix();
   8.319 +	glMatrixMode(GL_MODELVIEW);
   8.320 +	glPopMatrix();
   8.321 +
   8.322 +	glUseProgram(0);
   8.323 +	glPopAttrib();
   8.324 +}
   8.325 +#endif
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/prototype/src/renderer_deferred.h	Thu Aug 30 05:35:00 2012 +0300
     9.3 @@ -0,0 +1,35 @@
     9.4 +#ifndef RENDERER_DEFERRED_H_
     9.5 +#define RENDERER_DEFERRED_H_
     9.6 +
     9.7 +#include "renderer.h"
     9.8 +
     9.9 +#define MRT_COUNT	3
    9.10 +
    9.11 +class DeferredRenderer : public Renderer {
    9.12 +private:
    9.13 +	unsigned int fbo, rbuf_depth;
    9.14 +	unsigned int mrt_tex[MRT_COUNT];
    9.15 +	int tex_xsz, tex_ysz;
    9.16 +
    9.17 +	unsigned int mrt_prog;
    9.18 +	unsigned int deferred_omni, deferred_debug;
    9.19 +
    9.20 +	mutable unsigned int curr_prog;
    9.21 +
    9.22 +	bool create_fbo();
    9.23 +
    9.24 +public:
    9.25 +	DeferredRenderer();
    9.26 +	~DeferredRenderer();
    9.27 +
    9.28 +	bool init(int xsz, int ysz);
    9.29 +
    9.30 +	int get_tangent_location() const;
    9.31 +	unsigned int get_current_program() const;
    9.32 +
    9.33 +	void resize(int xsz, int ysz);
    9.34 +
    9.35 +	void render(const Level *level) const;
    9.36 +};
    9.37 +
    9.38 +#endif	// RENDERER_DEFERRED_H_
    10.1 --- a/prototype/src/tile.cc	Thu Aug 30 03:05:04 2012 +0300
    10.2 +++ b/prototype/src/tile.cc	Thu Aug 30 05:35:00 2012 +0300
    10.3 @@ -134,7 +134,7 @@
    10.4  {
    10.5  	int count = 0;
    10.6  
    10.7 -	int attr_loc = get_tangent_location();
    10.8 +	int attr_loc = rend->get_tangent_location();
    10.9  	if(attr_loc == -1) {
   10.10  		fprintf(stderr, "warning: failed to retrieve tangent attribute location while loading tile\n");
   10.11  	}