#version 330 core
precision highp float;

in vec2 ex_Uv;
in vec3 ex_Normal;
in vec3 ex_FragPos;
in vec2 ex_Ring;

out vec4 fragColor;

uniform vec3 uCameraPos;
uniform vec3 uBodyColor;
uniform vec3 uPatternColor;
uniform vec3 uBellyColor;
uniform vec3 uOutlineColor;
uniform float uPatternRepeats;
uniform float uOutlinePass;
uniform float uEyes;    // 0/1: draw eye dots on the head
uniform float uPattern; // 0/1: draw the zigzag back pattern
uniform float uGlint;   // specular glint strength (0 disables the highlight stripe)

const vec3 lightDir = normalize(vec3(-0.25, -0.5, -0.85));

void main()
{
	if (uOutlinePass > 0.5) {
		fragColor = vec4(uOutlineColor, 1.0);
		return;
	}

	// Zone colors: pale belly, adder-style triangle zigzag along the back, body color between
	float upness = ex_Ring.y;
	float tri = abs(fract(ex_Uv.x * uPatternRepeats) - 0.5) * 2.0; // triangle wave along the body
	float toothEdge = mix(0.92, 0.18, tri);                        // teeth reach down the flanks
	float patternMask = smoothstep(toothEdge, toothEdge + 0.06, upness) * uPattern;
	float bellyMask = smoothstep(-0.45, -0.58, upness);

	vec3 base = mix(uBodyColor, uPatternColor, patternMask);
	base = mix(base, uBellyColor, bellyMask);

	// Eyes: one dark dot with a glint on each upper flank of the head
	float theta = atan(ex_Ring.y, ex_Ring.x); // 0 = facing camera, pi/2 = top
	float eyeAngDist = min(abs(theta - 0.7), abs(theta - 2.44));
	vec2 eyeDelta = vec2((ex_Uv.x - 0.955) / 0.016, eyeAngDist / 0.55);
	float eyeMask = (1.0 - smoothstep(0.75, 1.0, length(eyeDelta))) * uEyes;
	vec2 glintDelta = vec2((ex_Uv.x - 0.958) / 0.007, (eyeAngDist - 0.12) / 0.22);
	float eyeGlint = (1.0 - smoothstep(0.7, 1.0, length(glintDelta))) * uEyes;

	// Toon lighting: quantized diffuse bands + darkened rim + a hard specular glint
	vec3 N = normalize(ex_Normal);
	vec3 V = normalize(uCameraPos - ex_FragPos);
	float ndl = dot(N, -lightDir);
	float band = ndl > 0.25 ? 1.0 : (ndl > -0.25 ? 0.78 : 0.58);
	float rim = smoothstep(0.62, 0.95, 1.0 - max(dot(N, V), 0.0));
	vec3 H = normalize(V - lightDir);
	float glint = step(0.988, max(dot(N, H), 0.0));

	vec3 col = base * band;
	col = mix(col, uOutlineColor, rim * 0.6); // rim doubles as the silhouette outline in single-pass mode
	col += vec3(0.85, 0.9, 0.8) * glint * 0.4 * uGlint;
	col = mix(col, vec3(0.03, 0.05, 0.04), eyeMask);
	col = mix(col, vec3(0.95, 0.97, 0.9), eyeGlint);
	fragColor = vec4(col, 1.0);
}
