<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebGL Deformable Mirror</title>
    <script src="static/viridis.js"></script>
    <script src="static/gl-matrix-min.js"></script>
    <style>
      body { margin: 0; }
      canvas { display: block; }
    </style>
  </head>
  <body>
      
    <canvas id="webgl-canvas" width="800" height="800"></canvas>
    <script>
      
    let lastX, lastY;
    let isDragging = false;
    let panX = -0.2, panY = 0;
    let tiltX = 0.3, tiltY = -1.0;
    let zoom = 0.5;

    function initShaderProgram(gl, vsSource, fsSource) {
        const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
        const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

        const shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertexShader);
        gl.attachShader(shaderProgram, fragmentShader);
        gl.linkProgram(shaderProgram);

        if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
            console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
            return null;
        }

        return shaderProgram;
    }

      function loadShader(gl, type, source) {
          const shader = gl.createShader(type);
          gl.shaderSource(shader, source);
          gl.compileShader(shader);

          if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
              console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
              gl.deleteShader(shader);
              return null;
          }

          return shader;
      }
      
      function initBuffers(gl, vertices, zValues) {
          const positionsBuffer = gl.createBuffer();
          gl.bindBuffer(gl.ARRAY_BUFFER, positionsBuffer);

          // Flatten the vertices array and concatenate with zValues
          const combinedData = [];
          for (let i = 0; i < vertices.length; i++) {
              combinedData.push(vertices[i][0], vertices[i][1], zValues[i]);
          }
          
          //gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices.flat()), gl.STATIC_DRAW);
          gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(combinedData), gl.STATIC_DRAW);

          const aPosition = gl.getAttribLocation(shaderProgram, 'aPosition');
          //gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
          gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);
          gl.enableVertexAttribArray(aPosition);
          
          const zBuffer = gl.createBuffer();
          gl.bindBuffer(gl.ARRAY_BUFFER, zBuffer);
          gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(zValues), gl.STATIC_DRAW);

          const aZValue = gl.getAttribLocation(shaderProgram, 'aZValue');
          gl.vertexAttribPointer(aZValue, 1, gl.FLOAT, false, 0, 0);
          gl.enableVertexAttribArray(aZValue);
      }
                              
    function drawScene(gl, vertices, zValues) {

    console.log(zoom, panX, panY, tiltX, tiltY)
    
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);

        // Set view matrix
        const viewMatrix = mat4.create();
        mat4.translate(viewMatrix, viewMatrix, [panX, panY, 0]);
        mat4.rotateX(viewMatrix, viewMatrix, tiltX);
        mat4.rotateY(viewMatrix, viewMatrix, tiltY);
        mat4.scale(viewMatrix, viewMatrix, [zoom, zoom, 1]);

        // Set view matrix uniform
        const uViewMatrix = gl.getUniformLocation(shaderProgram, 'uViewMatrix');
        gl.uniformMatrix4fv(uViewMatrix, false, viewMatrix);

        // Draw circles
        gl.drawArrays(gl.POINTS, 0, vertices.length);
    }

    function handleMouseDown(event) {
        isDragging = true;
        lastX = event.clientX;
        lastY = event.clientY;
    }

    function handleMouseUp() {
        isDragging = false;
    }

    function handleMouseMove(event) {
        if (!isDragging) return;
        const deltaX = event.clientX - lastX;
        const deltaY = event.clientY - lastY;
        lastX = event.clientX;
        lastY = event.clientY;
        tiltX += deltaY * 0.01;
        tiltY += deltaX * 0.01;
        drawScene(gl, vertices, zValues);
    }

    function handleWheel(event) {
        zoom += event.deltaY * -0.001;
        drawScene(gl, vertices, zValues);
    }

    const canvas = document.getElementById('webgl-canvas');
    const gl = canvas.getContext('webgl');

    if (!gl) {
        alert('Unable to initialize WebGL. Your browser may not support it.');
    }

    const vertexShaderSource = `
        attribute vec3 aPosition;
        attribute float aZValue;
        uniform mat4 uViewMatrix;
        varying float vZValue;
        void main() {
            gl_Position = uViewMatrix * vec4(aPosition, 1.0);
            gl_PointSize = 4.0;
            vZValue = aZValue;
        }
    `;
      

      const zValues = Array(97).fill(0.2)
      zValues[10] = +0.4
      zValues[11] = -0.4

      
    const fragmentShaderSource = `                                
    precision mediump float;                                        
    varying float vZValue;                                          
    uniform float minZValue;                                        
    uniform float maxZValue;                                        
                                                                    
    vec3 viridis(float t) {                                         
        const vec3 c0 = vec3(68, 1, 84) / 255.0;              
        const vec3 c1 = vec3(35, 136, 141) / 255.0;              
        const vec3 c2 = vec3(253, 231, 36) / 255.0;              
        // Add more color values as needed                          
                                                                    
        // Interpolate between colors                               
        if (t <= 0.0) return c0;                              
        else if (t <= 0.5) return mix(c0, c1, t);             
        else if (t >= 0.5) return mix(c1, c2, t);             
       // else if (t >= 1.0) return c2;                               
    }                                                               
                                                                    
    void main() {                                                   
        // Normalize zValue to range [0, 1]                         
        float t = (vZValue - minZValue) / (maxZValue - minZValue);  
        // Get color from Viridis color scale                       
        vec3 color = viridis(t);                             
        gl_FragColor = vec4(color, 1.0);                            
    }                                                               
`;                                                                                      
      const shaderProgram = initShaderProgram(gl, vertexShaderSource, fragmentShaderSource);
    gl.useProgram(shaderProgram);

      // Pass the viridis array to the shader
      const viridisUniformLocation = gl.getUniformLocation(shaderProgram, 'uViridis');
      gl.uniform3fv(viridisUniformLocation, viridis.flat());
      
    
      const vertices = [
                                                  [0.0, 0.3], [0.0, 0.4], [0.0, 0.5], [0.0, 0.6], [0.0, 0.7],
                                      [0.1, 0.2], [0.1, 0.3], [0.1, 0.4], [0.1, 0.5], [0.1, 0.6], [0.1, 0.7], [0.1, 0.8],
                          [0.2, 0.1], [0.2, 0.2], [0.2, 0.3], [0.2, 0.4], [0.2, 0.5], [0.2, 0.6], [0.2, 0.7], [0.2, 0.8], [0.2, 0.9],
              [0.3, 0.0], [0.3, 0.1], [0.3, 0.2], [0.3, 0.3], [0.3, 0.4], [0.3, 0.5], [0.3, 0.6], [0.3, 0.7], [0.3, 0.8], [0.3, 0.9], [0.3, 1.0 ],
              [0.4, 0.0], [0.4, 0.1], [0.4, 0.2], [0.4, 0.3], [0.4, 0.4], [0.4, 0.5], [0.4, 0.6], [0.4, 0.7], [0.4, 0.8], [0.4, 0.9], [0.4, 1.0 ],
              [0.5, 0.0], [0.5, 0.1], [0.5, 0.2], [0.5, 0.3], [0.5, 0.4], [0.5, 0.5], [0.5, 0.6], [0.5, 0.7], [0.5, 0.8], [0.5, 0.9], [0.5, 1.0 ],
              [0.6, 0.0], [0.6, 0.1], [0.6, 0.2], [0.6, 0.3], [0.6, 0.4], [0.6, 0.5], [0.6, 0.6], [0.6, 0.7], [0.6, 0.8], [0.6, 0.9], [0.6, 1.0 ],
              [0.7, 0.0], [0.7, 0.1], [0.7, 0.2], [0.7, 0.3], [0.7, 0.4], [0.7, 0.5], [0.7, 0.6], [0.7, 0.7], [0.7, 0.8], [0.7, 0.9], [0.7, 1.0 ],
                          [0.8, 0.1], [0.8, 0.2], [0.8, 0.3], [0.8, 0.4], [0.8, 0.5], [0.8, 0.6], [0.8, 0.7], [0.8, 0.8], [0.8, 0.9],
                                      [0.9, 0.2], [0.9, 0.3], [0.9, 0.4], [0.9, 0.5], [0.9, 0.6], [0.9, 0.7], [0.9, 0.8],
                                                  [1.0, 0.3], [1.0, 0.4], [1.0, 0.5], [1.0, 0.6], [1.0, 0.7]
      ]
      
      
      initBuffers(gl, vertices, zValues);
      drawScene(gl, vertices, zValues);
      
      canvas.addEventListener('mousedown', handleMouseDown);
      canvas.addEventListener('mouseup', handleMouseUp);
      canvas.addEventListener('mousemove', handleMouseMove);
      canvas.addEventListener('wheel', handleWheel);
      
      
    </script>
  </body>
</html>
