Create 2D Circle in webGL (single triangle)

by codert

HTML

<script src="https://greggman.github.io/webgl-fundamentals/webgl/resources/webgl-utils.js"></script>
<script id="node-vertex-shader" type="x-shader/x-vertex">
  uniform vec2 u_resolution;
  attribute vec2 a_position;
  attribute vec2 a_center;
  attribute float a_radius;

  varying vec2 center;
  varying vec2 resolution;
  varying float radius;
   
  void main() {
    vec2 clipspace = a_position / u_resolution * 2.0 - 1.0;
    gl_Position = vec4(clipspace * vec2(1, -1), 0, 1);

    radius = a_radius;
    center = a_center;
    resolution = u_resolution;
  }
</script>
 
<script id="node-fragment-shader" type="x-shader/x-fragment">

  precision mediump float;

  varying vec2 center;
  varying vec2 resolution;
  varying float radius;

  void main() {
    vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);

    float x = gl_FragCoord.x;
    float y = resolution[1] - gl_FragCoord.y;

    float dx = center[0] - x;
    float dy = center[1] - y;
    float distance = sqrt(dx*dx + dy*dy);

    if ( distance < radius )
      gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0);
    else 
      gl_FragColor = color0;

  }
</script>

<canvas id="canvas" style="border: none;" width="30" height="30"></canvas>

JavaScript

function onLoad () {
     var canvas = document.getElementById("canvas");
    var gl = canvas.getContext("experimental-webgl");
    
    var vertexShaderNode = createShaderFromScriptElement(gl, "node-vertex-shader");
    var fragmentShaderNode = createShaderFromScriptElement(gl, "node-fragment-shader");
    var programNode = createProgram(gl, [vertexShaderNode, fragmentShaderNode]);
    gl.useProgram(programNode);
     
     
    var ATTRIBUTES = 5;
    var j = 0;
    var data = [];
    var circle = {x: 15, y: 15, r: 15};

    data[j++] = (circle.x - circle.r);
    data[j++] = (circle.y - circle.r);
    data[j++] = circle.x;
    data[j++] = circle.y;
    data[j++] = circle.r;

    data[j++] = (circle.x + (1 + Math.sqrt(2)) * circle.r);
    data[j++] = circle.y - circle.r;
    data[j++] = circle.x;
    data[j++] = circle.y;
    data[j++] = circle.r;

    data[j++] = (circle.x - circle.r);
    data[j++] = (circle.y + (1 + Math.sqrt(2)) * circle.r);
    data[j++] = circle.x;
    data[j++] = circle.y;
    data[j++] = circle.r;

    var dataBuffer = new Float32Array(data);
  
    var buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(
        gl.ARRAY_BUFFER, 
        dataBuffer,
        gl.STATIC_DRAW);

    var resolutionLocation = gl.getUniformLocation(programNode, "u_resolution");
    gl.uniform2f(resolutionLocation, canvas.width, canvas.height);

    var positionLocation = gl.getAttribLocation(programNode, "a_position");
    var centerLocation = gl.getAttribLocation(programNode, "a_center");
    var radiusLocation = gl.getAttribLocation(programNode, "a_radius");

    
    gl.enableVertexAttribArray(positionLocation);
    gl.enableVertexAttribArray(centerLocation);
    gl.enableVertexAttribArray(radiusLocation);

    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
    gl.vertexAttribPointer(centerLocation, 2, gl.FLOAT, false, ATTRIBUTES *...