WebGL - Drawing Points
WebGL - Drawing Points
Section titled “WebGL - Drawing Points”This chapter demonstrates the fundamental process of drawing simple points in WebGL. We’ll follow the core steps established earlier, adapting them for the gl.POINTS primitive type.
Core Steps for Drawing Points
Section titled “Core Steps for Drawing Points”Drawing points follows the same general workflow as drawing triangles or other primitives:
Step 1: Setup Canvas and WebGL Context
Get the canvas element and the WebGL rendering context (gl). Include error handling.
Step 2: Define Geometry (Vertices) and Buffers
Define the 3D coordinates for each point you want to draw. Store these coordinates in a Float32Array and transfer them to a WebGL Vertex Buffer Object (VBO) using gl.createBuffer, gl.bindBuffer, and gl.bufferData.
// Define coordinates for three points (X, Y, Z)const pointVertices = new Float32Array([ -0.5, 0.5, 0.0, // Point 1 0.0, 0.5, 0.0, // Point 2 -0.25, 0.0, 0.0 // Point 3]);
// ... (Create VBO and bufferData code) ...Step 3: Create and Compile Shaders
Write, compile, and link the vertex and fragment shaders.
- Vertex Shader: Takes the vertex position attribute (
a_position). It must output the final position togl_Position. Crucially, for points, you can control their size in pixels by writing to the built-ingl_PointSizevariable. - Fragment Shader: Determines the color of each point. Set
gl_FragColor.
// Vertex Shader for Pointsattribute vec3 a_position;uniform float u_pointSize; // Pass size from JS
void main() { gl_Position = vec4(a_position, 1.0); gl_PointSize = u_pointSize; // Set the point size}// Fragment Shader for Pointsprecision mediump float;
void main() { gl_FragColor = vec4(1.0, 0.8, 0.0, 1.0); // Orange color}Step 4: Link Shaders and Buffers
Get the location of the a_position attribute and any uniforms (like u_pointSize). Enable the attribute array (gl.enableVertexAttribArray) and configure its data source using gl.vertexAttribPointer to point to the VBO.
Step 5: Set Uniforms and Draw
Set the value for the u_pointSize uniform using gl.uniform1f. Clear the canvas, set the viewport, and then use gl.drawArrays(gl.POINTS, first, count) to render the points. count should be the number of points defined in your vertex buffer.
gl.drawArrays(gl.POINTS, 0, 3); // Draw 3 points starting from index 0Example: Drawing Three Points
Section titled “Example: Drawing Three Points”This complete example draws three distinct orange points.
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>WebGL Drawing Points</title> <style> body { margin: 0; overflow: hidden; background-color: #222; } canvas { display: block; border: 1px solid lightgray; } </style></head><body> <canvas id="webgl-canvas" width="500" height="500"></canvas>
<script> // --- Shader Sources --- const vsSource = ` attribute vec3 a_position; uniform float u_pointSize; void main() { gl_Position = vec4(a_position, 1.0); gl_PointSize = u_pointSize; } `;
const fsSource = ` precision mediump float; void main() { gl_FragColor = vec4(1.0, 0.8, 0.0, 1.0); // Orange } `;
// --- Utility: Create Shader (Error checking included) --- function createShader(gl, type, source) { /* ... (same as previous example) ... */ const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error(`Shader compilation error (${type === gl.VERTEX_SHADER ? 'Vertex' : 'Fragment'}):`, gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; }
// --- Utility: Create Program (Error checking included) --- function createProgram(gl, vsSource, fsSource) { /* ... (same as previous example) ... */ const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource); const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource); if (!vertexShader || !fragmentShader) return null; const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.error('Program linking error:', gl.getProgramInfoLog(program)); gl.deleteProgram(program); return null; } return program; }
// --- Main WebGL Initialization --- const canvas = document.getElementById('webgl-canvas'); const gl = canvas.getContext('webgl');
if (!gl) { alert('WebGL is not supported.'); throw new Error('WebGL not supported'); }
// --- Shader Program --- const shaderProgram = createProgram(gl, vsSource, fsSource); if (!shaderProgram) throw new Error('Failed to create shader program.');
// --- Geometry and Buffers --- const pointVertices = new Float32Array([ -0.5, 0.5, 0.0, // Point 1 (Top-left) 0.0, 0.5, 0.0, // Point 2 (Top-center) -0.25, 0.0, 0.0 // Point 3 (Left-center) ]);
const vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, pointVertices, gl.STATIC_DRAW);
// --- Attribute & Uniform Locations --- const positionAttribLocation = gl.getAttribLocation(shaderProgram, 'a_position'); const pointSizeUniformLocation = gl.getUniformLocation(shaderProgram, 'u_pointSize');
// --- Error Checking Locations --- if (positionAttribLocation < 0) console.error("Attribute 'a_position' not found"); if (!pointSizeUniformLocation) console.error("Uniform 'u_pointSize' not found");
// --- Configure Attribute Pointer --- gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // Bind before setting pointer gl.vertexAttribPointer( positionAttribLocation, // Location 3, // Size (x, y, z) gl.FLOAT, // Type false, // Normalized? 0, // Stride 0 // Offset ); gl.enableVertexAttribArray(positionAttribLocation);
// --- Set Uniforms and Draw --- gl.useProgram(shaderProgram); // Activate program before setting uniforms
const desiredPointSize = 10.0; gl.uniform1f(pointSizeUniformLocation, desiredPointSize);
// --- Drawing Settings --- gl.clearColor(0.15, 0.15, 0.15, 1.0); // Dark gray background gl.enable(gl.DEPTH_TEST); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
// --- Draw Call --- gl.drawArrays( gl.POINTS, // Primitive type 0, // Starting index 3 // Number of points to draw );
</script></body></html>Expected Output:
The code will display three distinct orange square points (size 10x10 pixels) on a dark gray background. One point will be near the top-left, one near the top-center, and one near the left-center of the canvas, according to the coordinates provided.
Further Exploration:
Section titled “Further Exploration:”- Change the
desiredPointSizevalue. - Add more points to the
pointVerticesarray and update the count ingl.drawArrays. - Modify the fragment shader to change the point color.
- Make the point size an attribute (
attribute float a_pointSize;) to give each point a different size (requires adding size data to the buffer and configuring another attribute pointer).