WebGL JavaScript

Using the Fragment Shader to Interpolate Angles

This JavaScript program demonstrates how to use the pixel coordiantes in the fragment shader interpolate angles in a WebGL program.

FragmentShaderAngleInterpolation.html

<!DOCTYPE html>
<html>
  <head>
    <title>XoaX.net's WebGL</title>

    <script  id="idVertexShader" type="c">
      attribute vec2 av2Vertex;
      void main() {
        gl_Position = vec4(av2Vertex, 0.0, 1.0);
      }
    </script>

    <script  id="idFragmantShader" type="c">
      precision mediump float;
      uniform float ufCanvasWidth;
      uniform float ufCanvasHeight;

      float fMax = sqrt(ufCanvasWidth*ufCanvasWidth/8.0 + ufCanvasHeight*ufCanvasHeight/8.0);
      float fMidX = ufCanvasWidth/2.0;
      float fMidY = ufCanvasHeight/2.0;
      void main() {
        // gl_FragCoord must be accessed inside main()
        // The angles are interpolated between these colors: 0 = red, 120 = green, 240 = blue
        float fCX = gl_FragCoord.x - fMidX;
        float fCY = gl_FragCoord.y - fMidY;
        float fTheta = (atan(fCY, fCX)*180.0/3.14159);
        float fR = sqrt(fCX*fCX + fCY*fCY)/fMax;
        vec4 v4Color = vec4(0.0, fR, fR, 1.0);
        // Angles are in the range -pi to pi or -180 to 180 after conversion.
        if (0.0 <= fTheta && 120.0 > fTheta) {
          v4Color = vec4(fR*(1.0 - fTheta/120.0), fR*(fTheta/120.0), 0.0, 1.0);
        } else if (-120.0 <= fTheta && 0.0 > fTheta) {
          fTheta = fTheta + 120.0;
          v4Color = vec4(fR*(fTheta/120.0), 0.0, fR*(1.0 - fTheta/120.0), 1.0);
        } else if (120.0 <= fTheta) { //0 to 60
          fTheta = fTheta - 120.0;
          v4Color = vec4(0.0, fR*(1.0 - fTheta/120.0), fR*(fTheta/120.0), 1.0);
        } else {
          fTheta = fTheta + 180.0; //0 to 60
          v4Color = vec4(0.0, fR*(.5 - fTheta/120.0), fR*(.5 + fTheta/120.0), 1.0);
        }
        gl_FragColor = v4Color;
        //gl_FragColor = vec4(gl_FragCoord.x/ufCanvasWidth, gl_FragCoord.x/ufCanvasWidth, gl_FragCoord.y/ufCanvasHeight, 1.0);
      }
    </script>

    <script type="text/javascript">
    var gqProgram = null;
    var gqGL = null;
    function CreateProgramAndContext() {
      // Get the WebGL Context
      var qCanvas = document.querySelector("#idCanvasWebGL");
      gqGL = qCanvas.getContext("webgl");

      // Compile the vertex shader
      var sVertexShaderCode = document.querySelector("#idVertexShader").text;
      var qVertexShader = gqGL.createShader(gqGL.VERTEX_SHADER);
      gqGL.shaderSource(qVertexShader, sVertexShaderCode);
      gqGL.compileShader(qVertexShader);

      // Compile the fragment shader
      var sFragmentShaderCode = document.querySelector("#idFragmantShader").text;
      var qFragmentShader = gqGL.createShader(gqGL.FRAGMENT_SHADER);
      gqGL.shaderSource(qFragmentShader, sFragmentShaderCode);
      gqGL.compileShader(qFragmentShader);

      // Compile and link the program
      gqProgram = gqGL.createProgram();
      gqGL.attachShader(gqProgram, qVertexShader);
      gqGL.attachShader(gqProgram, qFragmentShader);
      gqGL.linkProgram(gqProgram);
      gqGL.useProgram(gqProgram);
    }

    function CreateBuffers() {
      var fA = Math.sqrt(2) - 1.0;
      var faVertices = new Float32Array([0.0, 0.0,
          1.0, -fA,    1.0, fA,     fA, 1.0,   -fA, 1.0,
         -1.0, fA,    -1.0, -fA,   -fA, -1.0,   fA, -1.0,
         1.0, -fA
      ]);

      var qVerticesBuffer = gqGL.createBuffer();
      gqGL.bindBuffer(gqGL.ARRAY_BUFFER, qVerticesBuffer);
      gqGL.bufferData(gqGL.ARRAY_BUFFER, faVertices, gqGL.STATIC_DRAW);

      var qVertexLoc = gqGL.getAttribLocation(gqProgram, 'av2Vertex');
      gqGL.vertexAttribPointer(qVertexLoc, 2, gqGL.FLOAT, false, 0, 0);
      gqGL.enableVertexAttribArray(qVertexLoc);

      // Unbind the buffer
      gqGL.bindBuffer(gqGL.ARRAY_BUFFER, null);
    }

    function Initialization() {
      CreateProgramAndContext();
      CreateBuffers();
      var fCanvasWidth = gqGL.getUniformLocation(gqProgram, 'ufCanvasWidth');
      var fCanvasHeight = gqGL.getUniformLocation(gqProgram, 'ufCanvasHeight');
      gqGL.uniform1f(fCanvasWidth, gqGL.drawingBufferWidth);
      gqGL.uniform1f(fCanvasHeight, gqGL.drawingBufferHeight);

      gqGL.clearColor(0.7, 0.7, 0.7, 1.0);
      gqGL.clear(gqGL.COLOR_BUFFER_BIT);
      gqGL.drawArrays(gqGL.TRIANGLE_FAN, 0, 10);
    }
    </script>
  </head>
  <body onload="Initialization();">
    <canvas id="idCanvasWebGL" width="400", height="400" style="border:1px solid black"></canvas>
  </body>
</html>
 

Output

 
 

© 2007–2024 XoaX.net LLC. All rights reserved.