rts_glIntegrateTexture.h 4.62 KB
/*This class performs integration across a series of rectangular
texture samples.  Basically, this is a downsample using a large box
filter and can be used to sum the results of multiple calculations
that are combined in a single texture.*/

#include "rts_glRenderToTexture.h"
#include "rts_glShaderProgram.h"

#define MEAN		0
#define SUM			1
#define MIN			2
#define MAX			3


class rts_glIntegrateTexture
{
private:
	int x_sample_size;
	int y_sample_size;
	int x_sample_num;
	int y_sample_num;

	rts_glShaderProgram x_pass_mean;
	rts_glShaderProgram y_pass_mean;

	rts_glShaderProgram x_pass_min;
	rts_glShaderProgram y_pass_min;

	rts_glShaderProgram x_pass_max;
	rts_glShaderProgram y_pass_max;

	//this is a two-pass downsample
	rts_glRenderToTexture x_pass;
	rts_glRenderToTexture y_pass;

	void initialize_shaders();
	inline void x_pass_enable(int type, rts_glTextureMap texture);
	inline void x_pass_disable(int type);
	inline void y_pass_enable(int type);
	inline void y_pass_disable(int type);

public:
	//initialize the integrator with the number and size of samples
	void Init(int x_size, int y_size,
				int samples_x, int samples_y,
				rts_glTextureMap test);

	void Integrate(float* result, rts_glTextureMap texture, int type = MEAN);
	rts_glTextureMap getResultTexture(){return y_pass.GetTexture(0);}
};

void rts_glIntegrateTexture::initialize_shaders()
{
	//load and initialize the integration shaders
	x_pass_mean.AttachShader(GL_FRAGMENT_SHADER,
							"x_pass_mean.glsl");
	x_pass_mean.Compile();
	x_pass_mean.Link();
	cout<<"x_pass_mean.glsl"<<endl;
	x_pass_mean.PrintLog();
	//x_pass_program.AttachTextureMap("difference_tex",
	//							test);
	x_pass_mean.AttachGlobalUniform("templatesize", &x_sample_size);


	y_pass_mean.AttachShader(GL_FRAGMENT_SHADER,
							"y_pass_mean.glsl");
	y_pass_mean.Compile();
	y_pass_mean.Link();
	cout<<"y_pass_mean.glsl"<<endl;
	y_pass_mean.PrintLog();
	y_pass_mean.AttachTextureMap("xfunnel_tex",
								x_pass.GetTexture(0));
	y_pass_mean.AttachGlobalUniform("templatesize", &x_sample_size);

}

void rts_glIntegrateTexture::x_pass_enable(int type, rts_glTextureMap texture)
{
	x_pass_mean.BeginProgram();
	x_pass_mean.AttachTextureMap("difference_tex",
								texture);
	x_pass_mean.UpdateGlobalUniforms();
}

void rts_glIntegrateTexture::x_pass_disable(int type)
{
	x_pass_mean.EndProgram();
}

void rts_glIntegrateTexture::y_pass_enable(int type)
{
	y_pass_mean.BeginProgram();
	y_pass_mean.UpdateGlobalUniforms();
}

void rts_glIntegrateTexture::y_pass_disable(int type)
{
	y_pass_mean.EndProgram();
}


void rts_glIntegrateTexture::Init(int x_size, int y_size,
				int samples_x, int samples_y,
				rts_glTextureMap test)
{
	//set provate variables
	x_sample_size = x_size;
	y_sample_size = y_size;
	x_sample_num = samples_x;
	y_sample_num = samples_y;

	//initialize the integrator texture maps
	x_pass.Init(x_sample_num, y_sample_num*y_sample_size);
	x_pass.AddTexture(GL_TEXTURE_RECTANGLE_ARB, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT);
	y_pass.Init(x_sample_num, y_sample_num);
	y_pass.AddTexture(GL_TEXTURE_RECTANGLE_ARB, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT);

	initialize_shaders();	
}

void rts_glIntegrateTexture::Integrate(float* result, rts_glTextureMap texture, int type)
{
	
	x_pass.BeginRender(0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	x_pass.UseMaxViewport();
	gluOrtho2D(0.0, 1.0, 0.0, 1.0);

	x_pass_enable(MEAN, texture);

	int total_w = x_sample_size * x_sample_num;
	int total_h = y_sample_size * y_sample_num;

	//GLint prog;
	//glGetIntegerv(GL_CURRENT_PROGRAM, &prog);
	glBegin(GL_QUADS);
		glTexCoord2f(0.0, 0.0);	glVertex2f(0.0, 0.0);
		glTexCoord2f(total_w, 0.0); glVertex2f(1.0, 0.0);
		glTexCoord2f(total_w, total_h); glVertex2f(1.0, 1.0);
		glTexCoord2f(0.0, total_h);	glVertex2f(0.0, 1.0);
	glEnd();
	x_pass_disable(MEAN);
	glFinish();
	x_pass.EndRender();

	//funnel along Y
	y_pass.BeginRender(0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	y_pass.UseMaxViewport();
	gluOrtho2D(0.0, 1.0, 0.0, 1.0);
	
	//glColor3f(1.0, 0.0, 0.0);
	y_pass_enable(type);
	glBegin(GL_QUADS);
		glTexCoord2f(0.0, 0.0);	glVertex2f(0.0, 0.0);
		glTexCoord2f(x_sample_num, 0.0); glVertex2f(1.0, 0.0);
		glTexCoord2f(x_sample_num, total_h); glVertex2f(1.0, 1.0);
		glTexCoord2f(0.0, total_h);	glVertex2f(0.0, 1.0);
	glEnd();
	int fb;
	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb);
	y_pass_disable(type);
	y_pass.EndRender();

	y_pass.GetTexture(0).BeginTexture();
	glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GL_FLOAT, result);
	y_pass.GetTexture(0).EndTexture();
	
}