Ocean Lighting Issues (Pixelated)

Trying to implement my own shader and the vertex shader looks fine. Just can’t figure out why the pixels are pixelated and stripey looking. I feel like the normals are being calculated incorrectly or the higher frequency waves are making the normals go everywhere.

Code below:

         vertexShader: `
            #define numWaves 64
            

            struct Wave {
                float frequency;
                float amplitude;
                float phase;
                vec2 direction;
            };

            struct Light {
                vec3 position;
            };

            uniform float time;

            uniform Wave[32] waves;
            uniform Light light;
            uniform vec3 deepWaterColor;
            uniform vec3 shallowWaterColor;
            uniform vec3 sunColor;

            varying vec3 vPosition;
            varying vec3 vNormal;

            varying vec3 lighting;

            varying float distanceToLight;

            float calcWave(vec2 pos) {
                float height = 0.0;
                for(int i = 0; i < numWaves; i++) {
                    Wave wave = waves[i];
                    height += wave.amplitude * exp(sin(dot(wave.direction, vec2(pos.x, pos.y)) * wave.frequency + time * wave.phase) - 1.0) / 32.0;
                }
                return height;
            }

            vec3 getNormal(vec3 vPosition) {
                vec2 slope = vec2(0, 0);
                for(int i = 0; i < numWaves; i++) {
                    Wave wave = waves[i];
                    slope.x += wave.frequency * wave.amplitude * wave.direction.x * cos(dot(wave.direction, vPosition.xy) * wave.frequency + time * wave.phase) * 
                        exp( sin(dot(wave.direction, vPosition.xy) * wave.frequency + time * wave.phase) - 1.0);
                    slope.y += wave.frequency * wave.amplitude * wave.direction.y * cos(dot(wave.direction, vPosition.xy)  * wave.frequency + time * wave.phase) * 
                        exp( sin(dot(wave.direction, vPosition.xy) * wave.frequency + time * wave.phase) - 1.0);;

                }
                vec3 tangent = normalize(vec3(1, 0, slope.x));
                vec3 binormal = normalize(vec3(0, 1, slope.y));
                vec3 norm = cross(tangent, binormal);
                return normalize(norm);
            }


            vec3 getLighting(vec3 p, float specularHighlight) {
                vec3 lightDirection = normalize(light.position - p);
                vec3 lightColor = vec3(1.0, 1.0, 1.0);
                vec3 norm = getNormal(p);
                vec3 ambientColor = deepWaterColor;
                vec3 diffuseColor = vec3(0.0, 0.125, 0.225);
                float diffuseCoeff = max(dot(norm, lightDirection), 0.0);

                vec3 V_norm = normalize(cameraPosition - p);
                float specular = 0.5 * pow(dot(normalize(V_norm + lightDirection), norm), specularHighlight);
                
                vec3 fresnel = pow(1.0 - dot(V_norm, norm), 4.0) * sunColor;
                return diffuseColor * diffuseCoeff + specular + 0.03 * fresnel;
            }

            void main() {
                vec3 pos = position;

                pos.z += calcWave(pos.xy);
                lighting = getLighting(pos, 10.0);

                distanceToLight = length(light.position - pos);

                // Pass the updated position and normal to the fragment shader
                vPosition = pos;
    
                // Final position of the vertex
                gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
            
            }
        `,
        fragmentShader: `
            #define PI 3.1415926538

            struct Wave {
                float frequency;
                float amplitude;
                float phase;
                vec2 direction;
            };
            uniform vec3 deepWaterColor;
            uniform vec3 shallowWaterColor;


            varying vec3 vPosition;
            varying vec3 vNormal;
            varying vec3 lighting;

            varying float distanceToLight;

            vec3 lerp(vec3 a, vec3 b, float t) {
                return (1.0 - t) * a - t * b;
            }

            void main() {

                //float inverseLightIntensity = 13900.0 / distanceToLight;
                vec3 color = deepWaterColor + lighting * vec3(1.0);
                gl_FragColor = vec4(color, 1.0);
                
            }
        `,...
1 Like

Solved, I was calculating the light / normals in the vertex shader not the fragment shader which caused the blending to occur.

2 Likes