/*
    QGLView
    Copyright (C) 2017  Ivan Pelipenko peri4ko@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "renderer_simple.h"


RendererSimple::RendererSimple(QGLView * view_): GLRendererBase(view_), fbo(2)
, fbo_c(1, true, GL_RGBA32F) /// WARNING
{
	shader_fxaa = 0;
	shader = 0; /// WARNING
}


void RendererSimple::reloadShaders() {
	if (shader_fxaa == 0) {
		shader_fxaa = new QGLShaderProgram(view.context());
		loadShaders(shader_fxaa, "FXAA", "shaders");
	}
	/*if (shader == 0) {
		shader = new QGLShaderProgram(view.context()); /// WARNING
		loadShaders(shader, "test", "shaders");        /// WARNING
	}*/
}


void RendererSimple::resizeFBO(int w, int h) {
	fbo.resize(w, h);
	fbo_c.resize(w, h); /// WARNING
}


void RendererSimple::renderScene() {
	int passes = (view.lightsCount() - 1) / 8 + 1;
	//QMatrix4x4 pm = getGLMatrix(GL_PROJECTION_MATRIX), mvm = getGLMatrix(GL_MODELVIEW_MATRIX), pmvm = pm * mvm, lpm, lmvm, lpmvm;
	glSetCapEnabled(GL_MULTISAMPLE, view.isFeatureEnabled(QGLView::qglMSAA));
	if (passes < 1) passes = 1;
	//glEnable(GL_FOG);
	if (view.isFeatureEnabled(QGLView::qglFXAA)) fbo.bind();
	//glEnable(GL_TEXTURE_2D);
	if (passes > 1) {
		fbo.bind();
		fbo.setWriteBuffer(0);
		glClearFramebuffer();
	}
	glEnable(GL_RESCALE_NORMAL);
	for (int l = 0; l < passes; ++l) {
		if (passes > 1) fbo.setWriteBuffer(1);
		if (l == 0) {
			glClearFramebuffer(view.backColor());
			glEnableDepth();
		} else {
			glClearFramebuffer(Qt::black, false);
			glEnable(GL_DEPTH_TEST);
			glDepthMask(GL_FALSE);
			glDepthFunc(GL_EQUAL);
		}
		view.camera().apply(view.aspect);
		rp.cam_offset_matrix = view.camera().offsetMatrix();
		rp.prepare();
		setupLights(l, 8);
		
		
		/*fbo_c.bind();
		glClearFramebuffer();
		//shader->bind(); /// WARNING
		renderObjects(GLObjectBase::Solid, l, 0, true, view.isLightEnabled(), view.isFogEnabled());
		//shader->release(); /// WARNING
		if (QRect(QPoint(), fbo_c.size()).contains(mpos)) {
			//qDebug() << mpos;
			GLfloat data[4] = {0, 0, 0, 0};
			glReadPixels(mpos.x(), fbo_c.height() - mpos.y(), 1, 1, GL_RGBA, GL_FLOAT, data);
			//qDebug() << QVector3D(data[0], data[1], data[2]);
		}
		fbo_c.release();*/
		//qDebug() << rp.viewproj_matrix << (getGLMatrix(GL_PROJECTION_MATRIX)*getGLMatrix(GL_MODELVIEW_MATRIX));
		renderObjects(GLObjectBase::Solid, l, 0, true, view.isLightEnabled(), view.isFogEnabled());
		
		
		//renderObjects(GLObjectBase::Solid, l, 0, true, true, view.isFogEnabled());
		renderObjects(GLObjectBase::Transparent, l, 0, true, true, view.isFogEnabled());
		if (passes > 1) {
			glSetLightEnabled(false);
			glSetCapEnabled(GL_BLEND);
			glBlendFunc(GL_ONE, GL_ONE);
			glReleaseTextures();
			glBindTexture(GL_TEXTURE_2D, fbo.colorTexture(1));
			glDisableDepth();
			fbo.setWriteBuffer(0);
			glDrawQuad();
		}
	}
	if (view.isFeatureEnabled(QGLView::qglFXAA) || passes > 1) {
		fbo.release();
		//glClearFramebuffer();
		glActiveTextureChannel(0);
		glBindTexture(GL_TEXTURE_2D, fbo.colorTexture());
		glSetLightEnabled(false);
		glSetCapEnabled(GL_BLEND, false);
		glDisableDepth();
		if (view.isFeatureEnabled(QGLView::qglFXAA)) {
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			shader_fxaa->bind();
			shader_fxaa->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height()));
			glDrawQuad();
			shader_fxaa->release();
		} else {
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glDrawQuad();
		}
	}
}
