float textureSmooth(in vec2 coord) {
	coord += 0.5f;
	vec2 whole = floor(coord);
	vec2 part  = curve(coord - whole);
	coord = whole + part - 0.5f;
	return texture(noisetex, coord * rcp(256.0)).x;
}

float WaterHeight(in vec2 p) {
    float wavesTime = frameTimeCounter * 1.2 * WATER_WAVE_SPEED;
	
	vec2 pos = p;
	pos.y *= 0.8;
	
    float wave = 0.0;
	
#if WATER_STYLE == 0
    // Стиль 0: Оригинальная вода (как и просил, 1в1 без изменений)
	wave += textureSmooth((pos + vec2(0.0, pos.x * 0.5 - wavesTime)) * 0.6) * 0.5;
	wave += textureSmooth((pos + vec2(wavesTime * 0.7, pos.x * 0.3 + wavesTime * 0.2)) * 1.2) * 0.35;
	wave += textureSmooth((pos - vec2(wavesTime * 0.4, pos.x * 0.6 - wavesTime * 0.5)) * 2.0) * 0.2;
	wave += textureSmooth((pos + vec2(wavesTime * 0.3, -pos.x * 0.2 + wavesTime * 0.3)) * 3.2) * 0.08;

#elif WATER_STYLE == 1
    // Стиль 1: Гладкие волны (крупные изгибы, микро-волн почти нет)
	wave += textureSmooth((pos + vec2(0.0, pos.x * 0.5 - wavesTime)) * 0.4) * 0.65;
	wave += textureSmooth((pos + vec2(wavesTime * 0.5, pos.x * 0.2 + wavesTime * 0.3)) * 0.8) * 0.3;
	wave += textureSmooth((pos - vec2(wavesTime * 0.3, pos.x * 0.4 - wavesTime * 0.4)) * 1.8) * 0.05;

#elif WATER_STYLE == 2
    // Стиль 2: Волны океана (направленные, вытянутые, с характерным накатом)
    vec2 oceanPos = pos * vec2(0.3, 0.9);
	wave += textureSmooth((oceanPos + vec2(0.0, -wavesTime * 1.2)) * 0.5) * 0.55;
	wave += textureSmooth((oceanPos + vec2(wavesTime * 0.4, -wavesTime * 0.8)) * 1.2) * 0.35;
	wave += textureSmooth((pos + vec2(-wavesTime * 0.5, pos.x * 0.2 - wavesTime)) * 2.5) * 0.1;

#elif WATER_STYLE == 3
    // Стиль 3: SEUS-стиль (имитация острых хребтов через инвертированный модуль шума)
    float w1 = abs(textureSmooth((pos + vec2(wavesTime * 0.8, -wavesTime)) * 0.5) - 0.5);
    float w2 = abs(textureSmooth((pos + vec2(-wavesTime * 0.6, pos.x * 0.5 - wavesTime * 0.8)) * 0.8) - 0.5);
    float w3 = abs(textureSmooth((pos + vec2(wavesTime * 0.4, wavesTime * 0.5)) * 1.5) - 0.5);
    wave += (1.0 - w1 * 2.0) * 0.45;
    wave += (1.0 - w2 * 2.0) * 0.35;
    wave += (1.0 - w3 * 2.0) * 0.20;

#elif WATER_STYLE == 4
    // Стиль 4: Реалистичные волны (сложный микс мягких и резких частот)
	wave += textureSmooth((pos + vec2(wavesTime * 0.2, pos.x * 0.1 - wavesTime * 0.5)) * 0.5) * 0.45;
	wave += textureSmooth((pos + vec2(-wavesTime * 0.3, pos.x * 0.3 + wavesTime * 0.4)) * 1.0) * 0.30;
	wave += textureSmooth((pos + vec2(wavesTime * 0.5, -pos.x * 0.2 - wavesTime * 0.6)) * 2.0) * 0.15;
	wave += textureSmooth((pos + vec2(-wavesTime * 0.7, pos.x * 0.5 + wavesTime * 0.8)) * 4.0) * 0.10;

#elif WATER_STYLE == 5
    // Стиль 5: HQ - HD волны (максимум октав, высокая детализация воды вблизи)
	wave += textureSmooth((pos + vec2(0.0, pos.x * 0.5 - wavesTime)) * 0.6) * 0.40;
	wave += textureSmooth((pos + vec2(wavesTime * 0.7, pos.x * 0.3 + wavesTime * 0.2)) * 1.2) * 0.25;
	wave += textureSmooth((pos - vec2(wavesTime * 0.4, pos.x * 0.6 - wavesTime * 0.5)) * 2.0) * 0.15;
	wave += textureSmooth((pos + vec2(wavesTime * 0.3, -pos.x * 0.2 + wavesTime * 0.3)) * 3.2) * 0.10;
    wave += textureSmooth((pos + vec2(-wavesTime * 0.5, pos.x * 0.4 + wavesTime * 0.4)) * 5.0) * 0.06;
    wave += textureSmooth((pos + vec2(wavesTime * 0.6, pos.x * 0.1 - wavesTime * 0.6)) * 8.0) * 0.04;
#endif

	#if defined DISTANT_HORIZONS
		float distFactor = dot(abs(dFdx(p) + dFdy(p)), vec2(2e2 / dhFarPlane));
	#else
		float distFactor = dot(abs(dFdx(p) + dFdy(p)), vec2(80.0 / far));
	#endif

	return wave / (0.8 + distFactor);
}

vec3 GetWavesNormal(in vec2 position) {

	float dist = length(position);
	#if defined DISTANT_HORIZONS
		float delta = mix(0.005, 0.05, smoothstep(5.0, 100.0, dist));
	#else
		float delta = mix(0.005, 0.04, smoothstep(5.0, 60.0, dist));
	#endif
	
	float wavesCenter = WaterHeight(position);

	float wavesLeft   = WaterHeight(position + vec2(-delta, 0.0));
	float wavesRight  = WaterHeight(position + vec2(delta, 0.0));
	float wavesDown   = WaterHeight(position + vec2(0.0, -delta));
	float wavesUp     = WaterHeight(position + vec2(0.0, delta));

	vec2 wavesNormal;
	wavesNormal.x = (wavesLeft - wavesRight) * 0.5; 
	wavesNormal.y = (wavesDown - wavesUp) * 0.5;    

	return normalize(vec3(wavesNormal * WATER_WAVE_HEIGHT, 0.4));
}