WebGL - Graphics Pipeline
WebGL - Graphics Pipeline
Section titled “WebGL - Graphics Pipeline”The WebGL graphics pipeline (or rendering pipeline) is the sequence of steps WebGL takes to transform your 3D scene description (vertices, shaders, textures) into the 2D image displayed on your canvas. Understanding this process helps in optimizing performance and debugging rendering issues.
Overview
Section titled “Overview”The pipeline involves stages executed on the CPU (via JavaScript) and stages executed on the GPU (fixed-function hardware and programmable shaders). Data flows from your application code, through the pipeline, ultimately resulting in pixels in the framebuffer.
Conceptual Stages of the Pipeline:
Section titled “Conceptual Stages of the Pipeline:”1. JavaScript Application (CPU)
Section titled “1. JavaScript Application (CPU)”- Data Preparation: Define vertex coordinates, colors, texture coordinates, indices using JavaScript Typed Arrays.
- Resource Allocation: Create WebGL resources like buffers (
gl.createBuffer), textures (gl.createTexture), shader programs (gl.createProgram). - Data Transfer: Upload data from JavaScript Typed Arrays to GPU buffers (
gl.bufferData) and textures (gl.texImage2D). - Shader Compilation/Linking: Compile GLSL shader code (
gl.compileShader) and link into a program (gl.linkProgram). - State Configuration: Set various WebGL states (viewport, clear color, depth test, blend functions, active texture unit).
- Attribute/Uniform Setup: Configure how vertex attributes read data from buffers (
gl.vertexAttribPointer,gl.enableVertexAttribArray) and set uniform values (gl.uniform*). - Issuing Draw Calls: Instruct the GPU to render using
gl.drawArraysorgl.drawElements.
2. Vertex Fetching (GPU)
Section titled “2. Vertex Fetching (GPU)”Based on the draw call (drawArrays or drawElements) and the attribute configurations (vertexAttribPointer), the GPU fetches the required vertex data from the bound VBOs (and IBO if using drawElements).
3. Vertex Shader (GPU - Programmable)
Section titled “3. Vertex Shader (GPU - Programmable)”- Receives vertex attributes (position, color, etc.) and uniforms.
- Performs calculations like transformations (Model-View-Projection), lighting calculations per vertex, texture coordinate generation.
- Must output the final vertex position in Homogeneous Clip Space coordinates to the built-in
gl_Positionvariable. - Can pass interpolated data (like color, texture coords) to the fragment shader via
varyingvariables.
4. Primitive Assembly (GPU - Fixed Function)
Section titled “4. Primitive Assembly (GPU - Fixed Function)”The transformed vertices are assembled into geometric primitives (points, lines, triangles) according to the mode specified in the draw call and the vertex order/indices.
5. Rasterization (GPU - Fixed Function)
Section titled “5. Rasterization (GPU - Fixed Function)”- Clipping: Discarding parts of primitives outside the [-1, +1] clip space volume.
- Perspective Divide: Dividing clip space coordinates (x, y, z) by w to get Normalized Device Coordinates (NDC).
- Viewport Transform: Mapping NDC coordinates to window (pixel) coordinates based on
gl.viewport. - Culling: Optionally discarding front-facing or back-facing triangles (
gl.enable(gl.CULL_FACE)). - Interpolation: Calculating the values of
varyingvariables for each pixel (‘fragment’) inside the primitive by smoothly blending the values from the primitive’s vertices.
6. Fragment Shader (GPU - Programmable)
Section titled “6. Fragment Shader (GPU - Programmable)”- Receives interpolated
varyingvalues from the vertex shader. - Receives uniforms.
- Performs operations like texture sampling (
texture2D), per-pixel lighting calculations, fog effects. - Must output the final RGBA color of the fragment to the built-in
gl_FragColorvariable (in WebGL 1).
7. Per-Fragment Operations (GPU - Fixed Function)
Section titled “7. Per-Fragment Operations (GPU - Fixed Function)”- Pixel Ownership Test: (Internal) Determines if the pixel belongs to the WebGL context.
- Scissor Test: Discards fragments outside a defined rectangle (
gl.scissor). - Stencil Test: Compares/modifies values in the stencil buffer (
gl.stencilFunc,gl.stencilOp). - Depth Test: Compares the fragment’s depth with the depth buffer (
gl.depthFunc). Discards hidden fragments. - Blending: Combines the fragment’s color with the color buffer (
gl.blendFunc). - Dithering: (Optional) Simulates more colors.
If a fragment passes all enabled tests, its color, depth, and stencil values are written to the corresponding buffers in the framebuffer.
8. Framebuffer (GPU Memory)
Section titled “8. Framebuffer (GPU Memory)”The final destination holding the rendered image (color buffer) and associated depth/stencil information. By default, this is the buffer associated with the HTML canvas element, which is then displayed by the browser.
Key Takeaways
Section titled “Key Takeaways”- CPU Role: Setup, data preparation, state management, initiating draws.
- GPU Role: Massively parallel execution of vertex/fragment shaders, fixed-function geometry processing and testing.
- Programmable Stages: Vertex Shader and Fragment Shader give developers control.
- Data Flow: Data moves from JS -> Buffers -> Vertex Shader -> Rasterizer -> Fragment Shader -> Framebuffer.
- Performance: Minimize CPU-GPU communication (use buffers), optimize shaders, leverage fixed-function tests (like depth test) efficiently.