#version 450

layout (location = 0) in vec3 in_position;
layout (location = 1) in vec3 in_normal;
layout (location = 2) in vec2 in_texture_coordinates;

layout (binding = 0) uniform UniformBuffer {
	vec4 color;
	mat4 modelMatrix;
	mat4 modelMatrixForNormals;
	mat4 viewProjMatrix;
	vec4 cameraPosition;
	vec4 materialProperties; // Renamed from illumination
	ivec4 userInput;
	float time;
} ub_data;

layout (binding = 1) uniform DirectionalLight {
	vec4 color;
	vec4 direction;
} dl_data;


layout (location = 0) out VertexData {
	vec3 positionWorld;
	vec3 normalWorld;
	vec2 textureCoordinates;
} vert_out;

void main() {
	vec4 position_world = ub_data.modelMatrix * vec4(in_position, 1.0);

	float base_amplitude = 2.0;
	float base_frequency = 10.0;
	float base_speed = 2.0;

	// Define multiple wave components
	// 1
	vec2 D1 = vec2(1.0, 0.0);
	float A1 = base_amplitude * 0.5;
	float F1 = base_frequency * 1.0;
	float S1 = base_speed * 1.0;

	// 2
	vec2 D2 = vec2(0.0, 1.0);
	float A2 = base_amplitude * 0.3;
	float F2 = base_frequency * 0.8;
	float S2 = base_speed * 0.7;

	// 3
	vec2 D3 = normalize(vec2(0.707, 0.707)); // 45 degrees
	float A3 = base_amplitude * 0.4;
	float F3 = base_frequency * 1.2;
	float S3 = base_speed * 1.1;

	// 4
	vec2 D4 = normalize(vec2(1.0, -0.5));
	float A4 = base_amplitude * 0.25;
	float F4 = base_frequency * 0.65;
	float S4 = base_speed * 0.85;

	vec3 animated_position = in_position;
	animated_position.y = 0.0;

	float k1 = dot(D1, vec2(in_position.x, in_position.z)) * F1 + ub_data.time * S1;
	float k2 = dot(D2, vec2(in_position.x, in_position.z)) * F2 + ub_data.time * S2;
	float k3 = dot(D3, vec2(in_position.x, in_position.z)) * F3 + ub_data.time * S3;
	float k4 = dot(D4, vec2(in_position.x, in_position.z)) * F4 + ub_data.time * S4;

	animated_position.y += A1 * sin(k1);
	animated_position.y += A2 * cos(k2); // Using cos for some variation from sin
	animated_position.y += A3 * sin(k3);
	animated_position.y += A4 * cos(k4); // Using cos for some variation from sin

	position_world = ub_data.modelMatrix * vec4(animated_position, 1.0);
	
	vert_out.positionWorld = position_world.xyz;
	gl_Position = ub_data.viewProjMatrix * position_world;
	
	const float normal_slope_scale = 0.01; // User adjusted value

	float df_dx = 0.0;
	float df_dz = 0.0;

	// Sum of derivatives from each wave component
	df_dx += A1 * D1.x * F1 * cos(k1);
	df_dz += A1 * D1.y * F1 * cos(k1);

	df_dx += A2 * D2.x * F2 * -sin(k2);
	df_dz += A2 * D2.y * F2 * -sin(k2);

	df_dx += A3 * D3.x * F3 * cos(k3);
	df_dz += A3 * D3.y * F3 * cos(k3);

	df_dx += A4 * D4.x * F4 * -sin(k4);
	df_dz += A4 * D4.y * F4 * -sin(k4);

	// Normal in object space: N_object = normalize(vec3(-df_dx, 1.0, -df_dz))
	// Apply scaling to the derivatives to make normals less extreme
	vec3 normal_object_space = normalize(vec3(-df_dx * normal_slope_scale, 1.0, -df_dz * normal_slope_scale));

	//  normal to world 
	vert_out.normalWorld = mat3(ub_data.modelMatrixForNormals) * normal_object_space;
	vert_out.textureCoordinates = in_texture_coordinates;
} 