WebGL JavaScript

Draw a Circle of Points

This JavaScript program demonstrates how to draw a circle composed of points in WebGL.

DrawACircleOfDots.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>XoaX.net's WebGL</title>
  </head>
  <style>
    canvas {
    	border: 1px solid black;
    	width: 800px;
    	height: 600px
    }
  </style>
  <body>
    <canvas id="idCanvas"></canvas>
    <script type="text/javascript" src="DrawACircleOfDots.js"></script>
  </body>
</html>

DrawACircleOfDots.js

'use strict';

// Vertex Shader
const ksVertexShader = `
attribute float faPointIndex;
uniform float fPointCount;
uniform vec2 daCanvasSize;

#define TWOPI radians(360.0)

void main() {
  float fFraction = faPointIndex/fPointCount;
  float fAngle = TWOPI*fFraction;
  float dRadius = 0.90;

  vec2 daPosition = vec2(cos(fAngle), sin(fAngle)) * dRadius;
  
  float fAspectRatio = daCanvasSize.y / daCanvasSize.x;
  vec2 daScale = vec2(fAspectRatio, 1);
  
  gl_Position = vec4(daPosition * daScale, 0, 1);
  gl_PointSize = 5.0;
}
`;

// Fragment Shader
const ksFragmentShader = `
precision mediump float;

void main() {
  gl_FragColor = vec4(1, .5, 0.0, 1);
}
`;

const kgqGL = document.querySelector('#idCanvas').getContext('webgl');

// Compile and link the program
function CreateTheProgram() {
	const saShaderType = ['VERTEX_SHADER', 'FRAGMENT_SHADER'];
	const saShaderCode = [ksVertexShader, ksFragmentShader];
	var qaCompiledShaders = [];
	// Compile the shaders
	for (var i = 0; i < 2; ++i) {
		// This is the equivalent of kgqGL.VERTEX_SHADER or kgqGL.FRAGMENT_SHADER
		const kqShader = kgqGL.createShader(kgqGL[saShaderType[i]]);
		kgqGL.shaderSource(kqShader, saShaderCode[i]);
		kgqGL.compileShader(kqShader);
		const bCompiled = kgqGL.getShaderParameter(kqShader, kgqGL.COMPILE_STATUS);
		if (!bCompiled) {
			const ksErrorLog = kgqGL.getShaderInfoLog(kqShader);
			console.log('There was an error compiling \'' + kqShader + '\':' + ksErrorLog + `\n`
				+ shaderSource.split('\n').map((l,i) => `${i + 1}: ${l}`).join('\n'));
			kgqGL.deleteShader(kqShader);
			return null;
		}
		qaCompiledShaders[i] = kqShader;
	}
	// Link the program
	const kqProgram = kgqGL.createProgram();
	kgqGL.attachShader(kqProgram, qaCompiledShaders[0]);
	kgqGL.attachShader(kqProgram, qaCompiledShaders[1]);
	kgqGL.linkProgram(kqProgram);
	const kbLinked = kgqGL.getProgramParameter(kqProgram, kgqGL.LINK_STATUS);
  if (!kbLinked) {
  	const ksErrorLog = kgqGL.getProgramInfoLog(kqProgram);
  	console.log('Error in program linking:' + ksErrorLog);
  	kgqGL.deleteProgram(kqProgram);
  	return null;
  }
	return kqProgram;
}
  

const kgProgram = CreateTheProgram();
// Vertex shader variables
const kqaPointIndicesLocation = kgqGL.getAttribLocation(kgProgram, 'faPointIndex');
const kqPointCountLocation = kgqGL.getUniformLocation(kgProgram, 'fPointCount');
const kqCanvasSizeLocation = kgqGL.getUniformLocation(kgProgram, 'daCanvasSize');
kgqGL.useProgram(kgProgram);

// Make a buffer
const kiPointCount = 100;
const kiaPointIndices = new Float32Array(kiPointCount);
kiaPointIndices.forEach((v, i) => { kiaPointIndices[i] = i; });

const kqIndexBuffer = kgqGL.createBuffer();
kgqGL.bindBuffer(kgqGL.ARRAY_BUFFER, kqIndexBuffer);
kgqGL.bufferData(kgqGL.ARRAY_BUFFER, kiaPointIndices, kgqGL.STATIC_DRAW);
kgqGL.enableVertexAttribArray(kqaPointIndicesLocation);
// Get the data out of the buffer
const kiEntriesPerIteration = 1;    // 1 components per iteration
const kiEntryType = kgqGL.FLOAT;		// the data is 32bit floats
const kbNormalize = false;				  // Do not alter the data to normalize it.
const kiStride = 0;									// Entries between iterations
const kiOffset = 0;        					// Entry index at the beginning of the buffer
kgqGL.vertexAttribPointer(kqaPointIndicesLocation, kiEntriesPerIteration, kiEntryType, kbNormalize, kiStride, kiOffset);

kgqGL.canvas.width = kgqGL.canvas.clientWidth;
kgqGL.canvas.height = kgqGL.canvas.clientHeight;
kgqGL.viewport(0, 0, kgqGL.canvas.width, kgqGL.canvas.height);

// Pass values to the shader
kgqGL.uniform1f(kqPointCountLocation, kiPointCount);
kgqGL.uniform2f(kqCanvasSizeLocation, kgqGL.canvas.width, kgqGL.canvas.height);

const kiArrayOffset = 0;
kgqGL.drawArrays(kgqGL.POINTS, kiArrayOffset, kiPointCount);
 

Output

 
 

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