/*
    QGLEngineShaders
    Ivan Pelipenko peri4ko@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.

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

#ifndef GLSHADERS_TYPES_H
#define GLSHADERS_TYPES_H

#include "gltypes.h"

namespace QGLEngineShaders {


/// VBO

// geometry
const GLsizei pos_offset           = 0;
const GLsizei normal_offset        = sizeof(QVector3D) + pos_offset;
const GLsizei tangent_offset       = sizeof(QVector3D) + normal_offset;
const GLsizei bitangent_offset     = sizeof(QVector3D) + tangent_offset;
const GLsizei tex_offset           = sizeof(QVector3D) + bitangent_offset;

// object
const GLsizei integers_offset      = 0;
const GLsizei color_offset         = sizeof(GLuint) * 4 + integers_offset;
const GLsizei modelmatrix_offset   = sizeof(QVector4D) + color_offset;
const GLsizei texturematrix_offset = sizeof(QVector4D) * 4 + modelmatrix_offset;

const GLsizei is_selected_offset   = 0;

const GLuint pos_loc               = 1;  // qgl_Vertex
const GLuint normal_loc            = 2;  // qgl_Normal
const GLuint tangent_loc           = 3;  // qgl_Tangent
const GLuint bitangent_loc         = 4;  // qgl_Bitangent
const GLuint tex_loc               = 5;  // qgl_Texture

const GLuint integers_loc          = 6;  // qgl_ObjectIntegers
const GLuint color_loc             = 8;  // qgl_ObjectColor
const GLuint modelmatrix_loc       = 9;  // qgl_ModelViewProjectionMatrix
const GLuint texturematrix_loc     = 13; // qgl_TextureMatrix

const GLuint is_selected_loc       = 7;  // qgl_ObjectSelected

#pragma pack(push, 1)
struct Vertex {
	QVector3D pos;
	QVector3D normal;
	QVector3D tangent;
	QVector3D bitangent;
	QVector2D tex;
};
struct Object {
	Object() {
		material = object_id = flags = 0;
		color                        = QVector4D(1, 1, 1, 1);
		QMatrix4x4().copyDataTo(modelmatrix);
		QMatrix2x3().transposed().copyDataTo(texturematrix);
	}
	GLuint material;
	GLuint object_id;
	union {
		GLuint flags;
		struct {
			GLuint f_accept_light      : 1;
			GLuint f_accept_fog        : 1;
			GLuint f_accept_cast_shadow: 1;
			GLuint f_accept_rec_shadow : 1;
		};
	};
	GLuint _reserve;
	QVector4D color;
	GLfloat modelmatrix[16];
	GLfloat texturematrix[6];
};
#pragma pack(pop)


/// UBO

enum BindingPoints {
	bpMaterials,
	bpLightParameters,
	bpLightPositions,
};

enum MapType {
	mtDiffuse   = 0,
	mtNormal    = 1,
	mtMetalness = 2,
	mtRoughness = 3,
	mtEmission  = 4,
	mtRelief    = 5,
};
enum TextureRole {
	trCoeffBRDF   = 10,
	trEnvironment = 11,
};
enum TextureArrayRole {
	tarEmpty       = 12,
	tarMaps        = 13,
	tarShadowsCone = 16,
	tarShadowsOmni = 17,
	tarDepthsCone  = 18,
	tarDepthsOmni  = 19,
};
enum EmptyMapRole {
	emrWhite,
	emrBlue,
	emrBlack,
	emrCount,
};
#define QGL_MAPS_COUNT 6
#pragma pack(push, 1)
struct QGLMap {
	QGLMap();
	GLfloat offset;
	GLfloat amount;
	QVector2D scale;
	GLuint array_index;
	GLuint map_index;
	GLfloat __res_2[2];
};
struct QGLMaterial {
	QGLMaterial();
	QVector4D color_diffuse;
	QVector4D color_emission;
	GLfloat transparency;
	GLfloat reflectivity;
	GLfloat iof;
	GLfloat dispersion;
	QGLMap map[QGL_MAPS_COUNT];
};
struct QGLLightParameter {
	QVector4D color;
	QVector4D decay_intensity; // [^0, ^1, ^2, intensity]
	QVector4D angles;          // [start, cos(start), end, cos(end)]
	GLfloat size  = 0.1f;
	GLfloat flags = 0;
	GLfloat _align[2];
	QGLMap map;
};
struct QGLLightPosition {
	QGLLightPosition() { QMatrix4x4().copyDataTo(shadowmatrix); }
	QVector4D position;
	QVector4D direction;
	GLfloat shadowmatrix[16];
};
#pragma pack(pop)

void prepareDrawGeom(QOpenGLExtraFunctions * f);
void prepareDrawObj(QOpenGLExtraFunctions * f);
void prepareDrawSel(QOpenGLExtraFunctions * f);


} // namespace QGLEngineShaders

#endif // GLSHADERS_TYPES_H
