/*
    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_HEADERS_H
#define GLSHADERS_HEADERS_H

namespace QGLEngineShaders {

const int max_materials      = 128;
const int max_lights         = 256;

const char qgl_common_head[] = "#version 400 core\n"
							   "";

const char qgl_vertex_head[] = "layout(location = 1 ) in vec3   qgl_Vertex        ;\n"
							   "layout(location = 2 ) in vec3   qgl_Normal        ;\n"
							   "layout(location = 3 ) in vec3   qgl_Tangent       ;\n"
							   "layout(location = 4 ) in vec3   qgl_Bitangent     ;\n"
							   "layout(location = 5 ) in vec2   qgl_Texture       ;\n"
							   "layout(location = 6 ) in uvec4  qgl_ObjectIntegers;\n"
							   "layout(location = 7 ) in uint   qgl_ObjectSelected;\n"
							   "layout(location = 8 ) in vec4   qgl_ObjectColor   ;\n"
							   "layout(location = 9 ) in mat4   qgl_ModelMatrix   ;\n"
							   "layout(location = 13) in mat2x3 qgl_TextureMatrix ;\n"
							   "out vec2 qgl_FragTexture;\n"
							   "flat out uint qgl_MaterialIndex;\n"
							   "uniform mat4 qgl_ViewMatrix;\n"
							   "uniform mat4 qgl_ViewProjMatrix;\n"
							   "mat3 qgl_getNormalMatrix()  {return inverse(mat3(qgl_ViewMatrix * qgl_ModelMatrix));}\n"
							   "mat3 qgl_getTangentMatrix() {return mat3(qgl_ViewMatrix * qgl_ModelMatrix);}\n"
							   "vec2 qgl_getFragTexture() {return (vec3(qgl_Texture, 1.f) * qgl_TextureMatrix).xy;}\n"
							   "vec4 qgl_ftransform() {return qgl_ViewProjMatrix * (qgl_ModelMatrix * vec4(qgl_Vertex, 1.f));}\n"
							   "#define qgl_Material    qgl_ObjectIntegers[0]\n"
							   "#define qgl_ObjectID    qgl_ObjectIntegers[1]\n"
							   "#define qgl_ObjectFlags qgl_ObjectIntegers[2]\n"
							   "";

const char qgl_material_head[] =
	"vec4 qgl_materialTexture(uint type, vec2 coord, vec4 tex_shift) {\n"
	"	coord *= qgl_material[qgl_MaterialIndex].map[type].scale;\n"
	"	vec4 t = texture(qgl_texture_array[qgl_material[qgl_MaterialIndex].map[type].array_index],\n"
	"						   vec3(coord, qgl_material[qgl_MaterialIndex].map[type].map_index));\n"
	"	t += tex_shift;\n"
	"	t.rgb = t.rgb * qgl_material[qgl_MaterialIndex].map[type].amount + qgl_material[qgl_MaterialIndex].map[type].offset;\n"
	"	return t;\n"
	"}\n"
	"";

const char qgl_fragment_head[]    = "in vec2 qgl_FragTexture;\n"
									"flat in uint qgl_MaterialIndex;\n"
									"out vec4 qgl_FragData[gl_MaxDrawBuffers];\n"
									"uniform vec2 qgl_ViewSize;\n"
									"#define qgl_FragColor qgl_FragData[0]\n"
									"";

const char qgl_geometry_head[]    = "";

const char qgl_structs[]          = "#define QGL_MAPS_COUNT    6\n"
									"#define QGL_MAP_DIFFUSE   0\n"
									"#define QGL_MAP_NORMAL    1\n"
									"#define QGL_MAP_METALNESS 2\n"
									"#define QGL_MAP_ROUGHNESS 3\n"
									"#define QGL_MAP_EMISSION  4\n"
									"#define QGL_MAP_RELIEF    5\n"
									"#define QGL_TEXTURE_ARRAY_EMPTY 0\n"
									"#define QGL_TEXTURE_ARRAY_MAPS  1\n"
									"struct QGLMap {\n"
									"	float offset;\n"
									"	float amount;\n"
									"	vec2 scale;\n"
									"	uint array_index;\n"
									"	uint map_index;\n"
									"};\n"
									"struct QGLMaterial {\n"
									"	vec4 color_diffuse;\n"
									"	vec4 color_emission;\n"
									"	float transparency;\n"
									"	float reflectivity;\n"
									"	float iof;\n"
									"	float dispersion;\n"
									"	QGLMap map[QGL_MAPS_COUNT];\n"
									"};\n"
									"struct QGLLightParameter {\n"
									"	vec4 color;\n"
									"	vec4 decay_intensity;\n"
									"	vec4 angles;\n"
									"	float size;\n"
									"	float flags;\n"
									"	QGLMap map;\n"
									"};\n"
									"struct QGLLightPosition {\n"
									"	vec4 position;\n"
									"	vec4 direction;\n"
									"	mat4 shadow_matrix;\n"
									"};\n"
									"";

const char qgl_uniform_material[] = "layout (std140) uniform QGLMaterialData {\n"
									"	QGLMaterial qgl_material[128];\n"
									"};\n"
									"uniform sampler2DArray qgl_texture_array[2];\n"
									"";

const char qgl_uniform_light[]    = "layout (std140) uniform QGLLightParameterData {\n"
									"	QGLLightParameter qgl_light_parameter[256];\n"
									"};\n"
									"layout (std140) uniform QGLLightPositionData {\n"
									"	QGLLightPosition qgl_light_position[256];\n"
									"};\n"
									"";

} // namespace QGLEngineShaders

#endif // GLSHADERS_HEADERS_H
