#include "Renderbuffer.h"

using namespace cg;

Renderbuffer::Renderbuffer(int w, int h, int sy, int texnum, bool adddepth)
{
	isError    = false;
	maxtexture = texnum;
	width      = w;
	height     = h;
	starty     = sy;

	glGenFramebuffers(1, &framebuffer);
	glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

	glGenTextures(maxtexture, renderTexture);
	for (int i = 0; i < maxtexture; i++) {
		glBindTexture(GL_TEXTURE_2D, renderTexture[i]);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

		glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, renderTexture[i], 0);
	}
	GLenum drawBuffer[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
	glDrawBuffers(maxtexture, drawBuffer);
	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
		isError = true;
		//printf("Render to texture initialization failed\n");
	}
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}


Renderbuffer::~Renderbuffer()
{
	glDeleteTextures(maxtexture, renderTexture);
	glDeleteFramebuffers(1, &framebuffer);
}

GLuint Renderbuffer::getFramebuffer() {
	return framebuffer;
}

GLuint Renderbuffer::getRenderTexture(int index) {
	if (index >= maxtexture) {
		return 0;
	}
	return renderTexture[index];
}

bool Renderbuffer::getError() {
	return isError;
}

void Renderbuffer::firstPass() {
	glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

	glClear(GL_COLOR_BUFFER_BIT);
	glViewport(0, 0, width, height);
}

void Renderbuffer::addShader(ShaderProgram *prg) {
	postprocessing = prg;
}

void Renderbuffer::secondPass() {
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glClear(GL_COLOR_BUFFER_BIT);
	glViewport(0, starty, width, height);
	glUseProgram(postprocessing->getProgramID());

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, renderTexture[0]);
	GLint loc = glGetUniformLocation(postprocessing->getProgramID(), "color");
	glUniform1i(loc, 0);

	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, renderTexture[1]);
	loc = glGetUniformLocation(postprocessing->getProgramID(), "bright");
	glUniform1i(loc, 1);

	loc = glGetUniformLocation(postprocessing->getProgramID(), "height");
	glUniform1i(loc, height);

	loc = glGetUniformLocation(postprocessing->getProgramID(), "fadeperc");
	glUniform1f(loc, fade);

	loc = glGetUniformLocation(postprocessing->getProgramID(), "kernelsize");
	glUniform1i(loc, kernelsize);

	loc = glGetUniformLocation(postprocessing->getProgramID(), "vignette");
	glUniform1f(loc, vignette);

	loc = glGetUniformLocation(postprocessing->getProgramID(), "avg");
	glUniform1i(loc, avg);

	loc = glGetUniformLocation(postprocessing->getProgramID(), "zoom");
	glUniform1f(loc, zoom);

	glBindVertexArray(vao);
	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}

void Renderbuffer::setFade(float f) {
	fade = f;
}

void Renderbuffer::setVertexArray(GLuint v) {
	vao = v;
}

void Renderbuffer::setKernelSize(int ks) {
	kernelsize = ks;
}

void Renderbuffer::setVignette(float v) {
	vignette = v;
}

void Renderbuffer::setAvg(int s) {
	avg = s;
}

void Renderbuffer::setZoom(float z) {
	zoom = z;
}