$input v_color0
$input v_normal
$input v_uv0
$input v_wpos

#include "../common.sh"

SAMPLER2D(s_texColor, 0);
SAMPLER3D(s_ditherSampler, 1);
SAMPLER2D(s_rampSampler, 2);
uniform vec4 u_time;
uniform vec4 u_dotColor;
uniform vec4 u_texInfo;
uniform vec4 u_baseColor;

float calcBrightness(vec3 lightPos, vec3 vertPos, vec3 normal)
{
	vec3 lightDir = normalize(lightPos - vertPos);
	float diffuse = max(0.0, dot(lightDir, normal));
	return diffuse * clamp(1.0 - distance(lightPos, vertPos) * 0.01, 0.0, 1.0);
}

float calcBrightnessDirectional(vec3 sunDir, vec3 normal)
{
	return max(0.0, dot(sunDir, normal));
}

vec3 desaturate(vec3 color)
{
	return vec3_splat(dot(color, vec3(0.33, 0.34, 0.33)));
}

float dither(float brightness, vec2 inputUv)
{
	float globalScale = 8;
	
	// constants
	float xRes = u_texInfo.z;
	float dotsPerSide = xRes / 16;
	float dotsTotal = dotsPerSide * dotsPerSide;
	float invXRes = 1 / xRes;
	float zRes = dotsTotal;
	float invZRes = 1 / zRes;
	
	float2 rampLookupUv = vec2((0.5 * invXRes + (1 - invXRes) * brightness), 0.5);
	float brightnessCurve = texture2D(s_rampSampler, rampLookupUv).r;
	
	// Magic dot frequency calculation
	float2 dx = ddx(inputUv);
	float2 dy = ddy(inputUv);
	float2x2 mat = float2x2(dx, dy);
	float4 vectorized = float4(dx, dy);
	float qq = dot(vectorized, vectorized);
	float rr = determinant(mat);
	float discriminantSqr = max(0.0, qq*qq - 4.0*rr*rr);
	float discriminant = sqrt(discriminantSqr);	
	float2 freq = sqrt(float2(qq + discriminant, qq - discriminant) / 2.0);

	// Figuring out how many dots we want
	float scaleExp = exp2(globalScale);
	float spacing = freq.y * scaleExp;
	spacing *= dotsPerSide * 0.125;

	float brightnessSpacingMultiplier = pow(brightnessCurve * 2 + 0.001, -(1 - 0.5));
	// float brightnessSpacingMultiplier = 1;
	spacing *= brightnessSpacingMultiplier;
	
	float spacingLog = log2(spacing);
	int patternScaleLevel = floor(spacingLog);
	float patternFractional = spacingLog - patternScaleLevel;
	vec2 uv = inputUv / exp2(patternScaleLevel);
	
	// patternFractional *= patternFractional;
	// patternFractional = smoothstep(0, 1, patternFractional);
	float subLayer = lerp(0.25 * dotsTotal, dotsTotal, 1 - patternFractional);
	subLayer = (subLayer - 0.5) * invZRes;
	
	float pattern = texture3D(s_ditherSampler, vec3(uv, subLayer)).r;	
	
	float contrast = 2 * scaleExp * brightnessSpacingMultiplier * 0.1;
	contrast *= pow(freq.y / freq.x, 1.0);
	float baseVal = lerp(0.5, brightness, saturate(1.05 / (1 + contrast)));
	float threshold = 1 - brightnessCurve + 0.6;
	
	return saturate((pattern - threshold) * contrast + baseVal);
}

void main()
{
	vec2 uv = vec2(1.0 - v_uv0.x, v_uv0.y);
	vec3 rawTex = texture2D(s_texColor, uv).xyz;
	vec3 col = rawTex * u_dotColor.xyz;
	float brightness = lerp(0.5, 0.9, calcBrightnessDirectional(vec3(0.5, 0.3, 1.0), v_normal));
	brightness = 1.0;
	gl_FragColor = vec4(col * brightness, 1.0);
}
