#version 330 core
layout (location = 0) in vec3 aPos; // Vertex position
layout (location = 1) in vec3 Normal; // Vertex position

out vec4 fragFBM;    // Pass the transformed normal to the fragment shader
out vec3 fragPosition;  // Pass the transformed position to the fragment shader


uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform float time;

float amplitude = 2.0;
float wave_length = 20.0;
float speed = 25.0f;
int waves = 32;
float k = 2.5;
float warpStrength=0.1f;




void main()
{
    // Initialize in world space
    vec3 position = vec3(model*vec4(aPos,1));
    float amplitudeSum = 0.0;
    
    // Tangent vectors for normal calculation
    vec3 tangentX = vec3(1.0, 0.0, 0.0); // Initial X tangent
    vec3 tangentZ = vec3(0.0, 0.0, 1.0); // Initial Z tangent

    // Wave parameters (decay each iteration)
    float currentAmplitude = amplitude;
    float currentWavelength = wave_length;
    float h=0f;
   
    for(int i = 0; i < waves; i++) {
        // Calculate wave direction and frequency
        float phase = float(i) * 0.5;
        vec2 direction = normalize(vec2(cos(phase), sin(phase)));
        float wave_frequency = 2.0 / currentWavelength;
        float wave_speed = speed * wave_frequency + float(i)*0.1;

        // Wave equation components
        float wave_dot = dot(direction, position.xz) * wave_frequency + time * wave_speed;
        float sinWave = sin(wave_dot);
        float cosWave = cos(wave_dot);

        // Height displacement (Equation 8a)
        float waveHeight = 2.0 * currentAmplitude * pow((sinWave + 1.0)/2.0, k);
        h += waveHeight;

        // Partial derivatives (Equation 8b)
        float partialDerivativeBase = pow((sinWave + 1.0)/2.0, k - 1.0);
        float dx = k * wave_frequency * partialDerivativeBase * cosWave;


        // Domain warping (applied AFTER derivative calculation)
        vec2 warpOffset = direction*dx * warpStrength * currentAmplitude;
        tangentX.y+= warpOffset.x;
        tangentZ.y+=warpOffset.y;
        position.xz += warpOffset;

        // Prepare for next iteration
        currentAmplitude *= 0.9;    // Amplitude decay
        currentWavelength *= 1.1;   // Wavelength increase
        amplitudeSum += currentAmplitude;
    }
 
    vec3 vertexFBM=vec3(0,h,0);
    
    vec4 finalPosition=model*vec4(aPos,1);
    finalPosition.xyz+=vertexFBM;
   vec3 n=cross(tangentX,tangentZ);
    fragFBM=normalize(vec4(n,h/amplitudeSum));
    // Output transformed position
    fragPosition = finalPosition.xyz;
    gl_Position = projection * view *finalPosition;

}









-------------------------------------------------------


#version 450 core

in vec4 fragFBM;   
in vec3 fragPosition; 

out vec4 FragColor; 


uniform vec3 cameraPos;
uniform vec3 sunDirection; 
uniform vec3 sunColor;
uniform mat3 normalMatrix;
vec3 tipColor= vec3(0.7f,0.8f,0.9f);
float tipStrength=0.3;
vec3 _DiffuseReflectance = vec3(0.0, 0.5, 1.0);





void main()
{
    vec3 lightDir = normalize(-vec3(-0.2f, -1.0f, -0.9f));  
    vec3 lightColor = vec3(1); 

    float height=0;
    vec3 normal=vec3(0);
    vec3 oceanColor = vec3(0.0, 0.3, 0.7); // Slightly darker to compensate
    float shininess = 64.0; // Lowered for softer specular
    height = fragFBM.w;
	normal = fragFBM.xyz;
normal= vec3(normal.x,-normal.y,normal.z);
    // Normalize inputs
     normal = normalize(normal);
    vec3 viewDir = normalize(cameraPos - fragPosition);
    
    // Ambient lighting
    vec3 ambient = 0.15 * oceanColor * lightColor;

      // Diffuse shading
    float ndotl = max(dot(lightDir, normal), 0.0);
    vec3 diffuseReflectance = _DiffuseReflectance / 3.14159; 
    vec3 diffuse = lightColor * ndotl ;

    // Specular reflection
    vec3 halfwayDir = normalize(lightDir + viewDir);
    float spec = pow(dot(normal, halfwayDir), shininess);
    vec3 specular = spec * lightColor ; // Reduce intensity

    // Fresnel Reflection (Schlick Approximation)
    float F0 = 0.02;  
    float fresnelFactor = F0 + (1.0 - F0) * pow(1.0 - max(dot(viewDir, normal), 0.0), 5.0);
    vec3 fresnelReflection = fresnelFactor * lightColor * 0.5; // Reduce impact

    vec3 foam = tipColor* pow(height,tipStrength);
    // Combine components
    vec3 finalColor = ambient + diffuse + specular + fresnelReflection+foam;
    finalColor = mix(finalColor, oceanColor, 0.5); // Blend with base color

    FragColor = vec4(finalColor, 1.0);
}