#version 430
#define YR_ACCURACY 4096.0f
#define UV_PER_METER (1.0f/0.256f)
#define QUAD_BG_TILE 64
#extension GL_ARB_bindless_texture : require

#include "ssbo_quad.glslshared"

flat in int instance;
smooth in vec2 frag_uv;
smooth in vec4 frag_pos;

layout(std430, binding=0) buffer QuadData
{
	ssbo_quad	quad[8192];
	uint		texbase[8192];
	uvec2		texbuf[];
};
layout(std430, binding=1) buffer Backgrounds
{
	uvec2	backgrounds[];
};

out vec4 out_Color;

uniform mat4 cam_mat;
#include "lighting.glslshared"

void main(void)
{
	//base color
	out_Color = vec4(unpackUnorm4x8(quad[instance].color).rgb, 1.0);
	
	vec2 hor_grad = dFdx(frag_uv);
	vec2 ver_grad = dFdy(frag_uv);

	//unpack packed field
	uvec4 pvals = uvec4(unpackUnorm4x8(quad[instance].twtbg) * 255);
	
	//background layer
	vec2 bgdim = quad[instance].uv_back[1] - quad[instance].uv_back[0];
	vec2 bg_uv = quad[instance].uv_back[0] + frag_uv * bgdim;
	vec2 horgrad_bg = hor_grad * bgdim;
	vec2 vergrad_bg = ver_grad * bgdim;
	uvec2 bghandle = backgrounds[pvals[1]];
	vec4 bg_color = vec4(0.0);
	if(bghandle != uvec2(0,0)) bg_color = textureGrad(sampler2D(bghandle), fract(bg_uv), horgrad_bg, vergrad_bg);
	if((int(quad[instance].flags) & QUAD_BG_TILE)==0) {
		if(any(lessThan(bg_uv, vec2(0.0))) || any(greaterThanEqual(bg_uv, vec2(1.0))))
			bg_color = vec4(0.0);
	}
	out_Color = (out_Color * (1.0 - bg_color.a)) + bg_color;

	//draw layer
	vec2 drawdim = quad[instance].size * UV_PER_METER;
	vec2 draw_uv = quad[instance].uv_draw + frag_uv * drawdim;
	vec2 horgrad_draw = hor_grad * drawdim;
	vec2 vergrad_draw = ver_grad * drawdim;
	ivec2 draw_tile = min(ivec2(7,7), ivec2(draw_uv));

	uint tex_idx = texbase[instance];
	tex_idx += draw_tile.y * int(pvals[0]);
	tex_idx += draw_tile.x;

	vec4 draw_color = vec4(0.0);
	if(texbuf[tex_idx] != uvec2(0,0)) draw_color = textureGrad(sampler2D(texbuf[tex_idx]), fract(draw_uv), horgrad_draw, vergrad_draw);
	out_Color = (out_Color * (1.0 - draw_color.a)) + draw_color;

	//lighting
	vec4 light_factor = light(cam_mat, quad[instance].normal.xyz, frag_pos);
	out_Color *= light_factor;
}
